summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGuy Harris <guy@alum.mit.edu>2002-01-11 08:21:02 +0000
committerGuy Harris <guy@alum.mit.edu>2002-01-11 08:21:02 +0000
commit30a043931e9f0382cb8516403a3e3dc6eb5a08dc (patch)
treeed2b952f6cb757b1d61c582b8d76806ba445d4a0
parentfeb5791d6ae22cca80342e84961273ddaaf52b6f (diff)
downloadwireshark-30a043931e9f0382cb8516403a3e3dc6eb5a08dc.tar.gz
From Jirka Novak:
Support for generating filter expressions based on packet list column values Support for adding filter expressions generated from column or protocol tree field values to the current expression rather than replacing the current expression svn path=/trunk/; revision=4522
-rw-r--r--AUTHORS8
-rw-r--r--doc/ethereal.pod.template1
-rw-r--r--epan/column-utils.c94
-rw-r--r--epan/column_info.h4
-rw-r--r--gtk/keys.h5
-rw-r--r--gtk/main.c336
-rw-r--r--gtk/main.h37
-rw-r--r--gtk/menu.c125
8 files changed, 556 insertions, 54 deletions
diff --git a/AUTHORS b/AUTHORS
index 5935043752..eb71b4cbd3 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -991,6 +991,14 @@ Dinesh Dutt <ddutt[AT]cisco.com> {
Nagarjuna Venna <nvenna[AT]Brixnet.com> {
Only display the reason in BYE RTCP packets if it's present
}
+
+Jirka Novak <j.novak[AT]netsystem.cz> {
+ Support for generating filter expressions based on packet list
+ column values
+ Support for adding filter expressions generated from column or
+ protocol tree field values to the current expression rather
+ than replacing the current expression
+}
Alain Magloire <alainm[AT]rcsm.ece.mcgill.ca> was kind enough to
give his permission to use his version of snprintf.c.
diff --git a/doc/ethereal.pod.template b/doc/ethereal.pod.template
index cdedd603ff..f0b7af1b82 100644
--- a/doc/ethereal.pod.template
+++ b/doc/ethereal.pod.template
@@ -1279,6 +1279,7 @@ B<http://www.ethereal.com>.
Jayaram V.R <vjayar[AT]cisco.com>
Dinesh Dutt <ddutt[AT]cisco.com>
Nagarjuna Venna <nvenna[AT]Brixnet.com>
+ Jirka Novak <j.novak[AT]netsystem.cz>
Alain Magloire <alainm[AT]rcsm.ece.mcgill.ca> was kind enough to give his
permission to use his version of snprintf.c.
diff --git a/epan/column-utils.c b/epan/column-utils.c
index dbae5d6ee3..c332f5816a 100644
--- a/epan/column-utils.c
+++ b/epan/column-utils.c
@@ -1,7 +1,7 @@
/* column-utils.c
* Routines for column utilities.
*
- * $Id: column-utils.c,v 1.9 2001/12/10 02:15:54 guy Exp $
+ * $Id: column-utils.c,v 1.10 2002/01/11 08:21:00 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
@@ -64,6 +64,8 @@ col_init(column_info *col_info, gint num_cols)
col_info->col_title = (gchar **) g_malloc(sizeof(gchar *) * num_cols);
col_info->col_data = (gchar **) g_malloc(sizeof(gchar *) * num_cols);
col_info->col_buf = (gchar **) g_malloc(sizeof(gchar *) * num_cols);
+ col_info->col_expr = (gchar **) g_malloc(sizeof(gchar *) * num_cols);
+ col_info->col_expr_val = (gchar **) g_malloc(sizeof(gchar *) * num_cols);
}
#if 0
@@ -115,6 +117,8 @@ col_clear(column_info *cinfo, gint el) {
if (cinfo->fmt_matx[i][el]) {
cinfo->col_buf[i][0] = 0;
cinfo->col_data[i] = cinfo->col_buf[i];
+ cinfo->col_expr[i][0] = '\0';
+ cinfo->col_expr_val[i][0] = '\0';
}
}
}
@@ -249,6 +253,8 @@ col_set_abs_date_time(frame_data *fd, column_info *cinfo, int col)
cinfo->col_buf[col][0] = '\0';
}
cinfo->col_data[col] = cinfo->col_buf[col];
+ strcpy(cinfo->col_expr[col],"frame.time");
+ strcpy(cinfo->col_expr_val[col],cinfo->col_buf[col]);
}
static void
@@ -257,6 +263,8 @@ col_set_rel_time(frame_data *fd, column_info *cinfo, int col)
display_signed_time(cinfo->col_buf[col], COL_MAX_LEN,
fd->rel_secs, fd->rel_usecs, USECS);
cinfo->col_data[col] = cinfo->col_buf[col];
+ strcpy(cinfo->col_expr[col],"frame.time_relative");
+ strcpy(cinfo->col_expr_val[col],cinfo->col_buf[col]);
}
static void
@@ -265,6 +273,8 @@ col_set_delta_time(frame_data *fd, column_info *cinfo, int col)
display_signed_time(cinfo->col_buf[col], COL_MAX_LEN,
fd->del_secs, fd->del_usecs, USECS);
cinfo->col_data[col] = cinfo->col_buf[col];
+ strcpy(cinfo->col_expr[col],"frame.time_delta");
+ strcpy(cinfo->col_expr_val[col],cinfo->col_buf[col]);
}
/* To do: Add check_col checks to the col_add* routines */
@@ -287,6 +297,8 @@ col_set_abs_time(frame_data *fd, column_info *cinfo, int col)
cinfo->col_buf[col][0] = '\0';
}
cinfo->col_data[col] = cinfo->col_buf[col];
+ strcpy(cinfo->col_expr[col],"frame.time");
+ strcpy(cinfo->col_expr_val[col],cinfo->col_buf[col]);
}
/* Add "command-line-specified" time.
@@ -319,13 +331,16 @@ col_set_cls_time(frame_data *fd, column_info *cinfo, int col)
}
static void
-col_set_addr(packet_info *pinfo, int col, address *addr, gboolean is_res)
+col_set_addr(packet_info *pinfo, int col, address *addr, gboolean is_res,
+ gboolean is_src)
{
guint32 ipv4_addr;
struct e_in6_addr ipv6_addr;
struct atalk_ddp_addr ddp_addr;
struct sna_fid_type_4_addr sna_fid_type_4_addr;
+ pinfo->cinfo->col_expr[col][0] = '\0';
+ pinfo->cinfo->col_expr_val[col][0] = '\0';
switch (addr->type) {
case AT_ETHER:
@@ -335,6 +350,12 @@ col_set_addr(packet_info *pinfo, int col, address *addr, gboolean is_res)
strncpy(pinfo->cinfo->col_buf[col], ether_to_str(addr->data), COL_MAX_LEN);
pinfo->cinfo->col_buf[col][COL_MAX_LEN - 1] = '\0';
pinfo->cinfo->col_data[col] = pinfo->cinfo->col_buf[col];
+ if (is_src)
+ strcpy(pinfo->cinfo->col_expr[col], "eth.src");
+ else
+ strcpy(pinfo->cinfo->col_expr[col], "eth.dst");
+ strncpy(pinfo->cinfo->col_expr_val[col], ether_to_str(addr->data), COL_MAX_LEN);
+ pinfo->cinfo->col_expr_val[col][COL_MAX_LEN - 1] = '\0';
break;
case AT_IPv4:
@@ -345,6 +366,12 @@ col_set_addr(packet_info *pinfo, int col, address *addr, gboolean is_res)
strncpy(pinfo->cinfo->col_buf[col], ip_to_str(addr->data), COL_MAX_LEN);
pinfo->cinfo->col_buf[col][COL_MAX_LEN - 1] = '\0';
pinfo->cinfo->col_data[col] = pinfo->cinfo->col_buf[col];
+ if (is_src)
+ strcpy(pinfo->cinfo->col_expr[col], "ip.src");
+ else
+ strcpy(pinfo->cinfo->col_expr[col], "ip.dst");
+ strncpy(pinfo->cinfo->col_expr_val[col], ip_to_str(addr->data), COL_MAX_LEN);
+ pinfo->cinfo->col_expr_val[col][COL_MAX_LEN - 1] = '\0';
break;
case AT_IPv6:
@@ -355,6 +382,12 @@ col_set_addr(packet_info *pinfo, int col, address *addr, gboolean is_res)
strncpy(pinfo->cinfo->col_buf[col], ip6_to_str(&ipv6_addr), COL_MAX_LEN);
pinfo->cinfo->col_buf[col][COL_MAX_LEN - 1] = '\0';
pinfo->cinfo->col_data[col] = pinfo->cinfo->col_buf[col];
+ if (is_src)
+ strcpy(pinfo->cinfo->col_expr[col], "ipv6.src");
+ else
+ strcpy(pinfo->cinfo->col_expr[col], "ipv6.dst");
+ strncpy(pinfo->cinfo->col_expr_val[col], ip6_to_str(&ipv6_addr), COL_MAX_LEN);
+ pinfo->cinfo->col_expr_val[col][COL_MAX_LEN - 1] = '\0';
break;
case AT_IPX:
@@ -362,6 +395,11 @@ col_set_addr(packet_info *pinfo, int col, address *addr, gboolean is_res)
ipx_addr_to_str(pntohl(&addr->data[0]), &addr->data[4]), COL_MAX_LEN);
pinfo->cinfo->col_buf[col][COL_MAX_LEN - 1] = '\0';
pinfo->cinfo->col_data[col] = pinfo->cinfo->col_buf[col];
+ if (is_src)
+ strcpy(pinfo->cinfo->col_expr[col], "ipx.src");
+ else
+ strcpy(pinfo->cinfo->col_expr[col], "ipx.dst");
+ strcpy(pinfo->cinfo->col_expr_val[col],pinfo->cinfo->col_buf[col]);
break;
case AT_SNA:
@@ -415,8 +453,10 @@ col_set_addr(packet_info *pinfo, int col, address *addr, gboolean is_res)
static void
col_set_port(packet_info *pinfo, int col, port_type ptype, guint32 port,
- gboolean is_res)
+ gboolean is_res, gboolean is_src)
{
+ pinfo->cinfo->col_expr[col][0] = '\0';
+ pinfo->cinfo->col_expr_val[col][0] = '\0';
switch (ptype) {
case PT_SCTP:
@@ -431,6 +471,12 @@ col_set_port(packet_info *pinfo, int col, port_type ptype, guint32 port,
strncpy(pinfo->cinfo->col_buf[col], get_tcp_port(port), COL_MAX_LEN);
else
snprintf(pinfo->cinfo->col_buf[col], COL_MAX_LEN, "%u", port);
+ if (is_src)
+ strcpy(pinfo->cinfo->col_expr[col], "tcp.srcport");
+ else
+ strcpy(pinfo->cinfo->col_expr[col], "tcp.dstport");
+ snprintf(pinfo->cinfo->col_expr_val[col], COL_MAX_LEN, "%u", port);
+ pinfo->cinfo->col_expr_val[col][COL_MAX_LEN - 1] = '\0';
break;
case PT_UDP:
@@ -438,6 +484,12 @@ col_set_port(packet_info *pinfo, int col, port_type ptype, guint32 port,
strncpy(pinfo->cinfo->col_buf[col], get_udp_port(port), COL_MAX_LEN);
else
snprintf(pinfo->cinfo->col_buf[col], COL_MAX_LEN, "%u", port);
+ if (is_src)
+ strcpy(pinfo->cinfo->col_expr[col], "udp.srcport");
+ else
+ strcpy(pinfo->cinfo->col_expr[col], "udp.dstport");
+ snprintf(pinfo->cinfo->col_expr_val[col], COL_MAX_LEN, "%u", port);
+ pinfo->cinfo->col_expr_val[col][COL_MAX_LEN - 1] = '\0';
break;
default:
@@ -458,6 +510,8 @@ fill_in_columns(packet_info *pinfo)
case COL_NUMBER:
snprintf(pinfo->cinfo->col_buf[i], COL_MAX_LEN, "%u", pinfo->fd->num);
pinfo->cinfo->col_data[i] = pinfo->cinfo->col_buf[i];
+ strcpy(pinfo->cinfo->col_expr[i], "frame.number");
+ strcpy(pinfo->cinfo->col_expr_val[i], pinfo->cinfo->col_buf[i]);
break;
case COL_CLS_TIME:
@@ -482,74 +536,74 @@ fill_in_columns(packet_info *pinfo)
case COL_DEF_SRC:
case COL_RES_SRC: /* COL_DEF_SRC is currently just like COL_RES_SRC */
- col_set_addr(pinfo, i, &pinfo->src, TRUE);
+ col_set_addr(pinfo, i, &pinfo->src, TRUE, TRUE);
break;
case COL_UNRES_SRC:
- col_set_addr(pinfo, i, &pinfo->src, FALSE);
+ col_set_addr(pinfo, i, &pinfo->src, FALSE, TRUE);
break;
case COL_DEF_DL_SRC:
case COL_RES_DL_SRC:
- col_set_addr(pinfo, i, &pinfo->dl_src, TRUE);
+ col_set_addr(pinfo, i, &pinfo->dl_src, TRUE, TRUE);
break;
case COL_UNRES_DL_SRC:
- col_set_addr(pinfo, i, &pinfo->dl_src, FALSE);
+ col_set_addr(pinfo, i, &pinfo->dl_src, FALSE, TRUE);
break;
case COL_DEF_NET_SRC:
case COL_RES_NET_SRC:
- col_set_addr(pinfo, i, &pinfo->net_src, TRUE);
+ col_set_addr(pinfo, i, &pinfo->net_src, TRUE, TRUE);
break;
case COL_UNRES_NET_SRC:
- col_set_addr(pinfo, i, &pinfo->net_src, FALSE);
+ col_set_addr(pinfo, i, &pinfo->net_src, FALSE, TRUE);
break;
case COL_DEF_DST:
case COL_RES_DST: /* COL_DEF_DST is currently just like COL_RES_DST */
- col_set_addr(pinfo, i, &pinfo->dst, TRUE);
+ col_set_addr(pinfo, i, &pinfo->dst, TRUE, FALSE);
break;
case COL_UNRES_DST:
- col_set_addr(pinfo, i, &pinfo->dst, FALSE);
+ col_set_addr(pinfo, i, &pinfo->dst, FALSE, FALSE);
break;
case COL_DEF_DL_DST:
case COL_RES_DL_DST:
- col_set_addr(pinfo, i, &pinfo->dl_dst, TRUE);
+ col_set_addr(pinfo, i, &pinfo->dl_dst, TRUE, FALSE);
break;
case COL_UNRES_DL_DST:
- col_set_addr(pinfo, i, &pinfo->dl_dst, FALSE);
+ col_set_addr(pinfo, i, &pinfo->dl_dst, FALSE, FALSE);
break;
case COL_DEF_NET_DST:
case COL_RES_NET_DST:
- col_set_addr(pinfo, i, &pinfo->net_dst, TRUE);
+ col_set_addr(pinfo, i, &pinfo->net_dst, TRUE, FALSE);
break;
case COL_UNRES_NET_DST:
- col_set_addr(pinfo, i, &pinfo->net_dst, FALSE);
+ col_set_addr(pinfo, i, &pinfo->net_dst, FALSE, FALSE);
break;
case COL_DEF_SRC_PORT:
case COL_RES_SRC_PORT: /* COL_DEF_SRC_PORT is currently just like COL_RES_SRC_PORT */
- col_set_port(pinfo, i, pinfo->ptype, pinfo->srcport, TRUE);
+ col_set_port(pinfo, i, pinfo->ptype, pinfo->srcport, TRUE, TRUE);
break;
case COL_UNRES_SRC_PORT:
- col_set_port(pinfo, i, pinfo->ptype, pinfo->srcport, FALSE);
+ col_set_port(pinfo, i, pinfo->ptype, pinfo->srcport, FALSE, TRUE);
break;
case COL_DEF_DST_PORT:
case COL_RES_DST_PORT: /* COL_DEF_DST_PORT is currently just like COL_RES_DST_PORT */
- col_set_port(pinfo, i, pinfo->ptype, pinfo->destport, TRUE);
+ col_set_port(pinfo, i, pinfo->ptype, pinfo->destport, TRUE, FALSE);
break;
case COL_UNRES_DST_PORT:
- col_set_port(pinfo, i, pinfo->ptype, pinfo->destport, FALSE);
+ col_set_port(pinfo, i, pinfo->ptype, pinfo->destport, FALSE, FALSE);
break;
case COL_PROTOCOL: /* currently done by dissectors */
@@ -559,6 +613,8 @@ fill_in_columns(packet_info *pinfo)
case COL_PACKET_LENGTH:
snprintf(pinfo->cinfo->col_buf[i], COL_MAX_LEN, "%u", pinfo->fd->pkt_len);
pinfo->cinfo->col_data[i] = pinfo->cinfo->col_buf[i];
+ strcpy(pinfo->cinfo->col_expr[i], "frame.pkt_len");
+ strcpy(pinfo->cinfo->col_expr_val[i], pinfo->cinfo->col_buf[i]);
break;
case NUM_COL_FMTS: /* keep compiler happy - shouldn't get here */
diff --git a/epan/column_info.h b/epan/column_info.h
index 48ad0383d1..cfe0c24a5c 100644
--- a/epan/column_info.h
+++ b/epan/column_info.h
@@ -1,7 +1,7 @@
/* column.h
* Definitions for column structures and routines
*
- * $Id: column_info.h,v 1.1 2001/04/01 03:42:00 hagbard Exp $
+ * $Id: column_info.h,v 1.2 2002/01/11 08:21:00 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
@@ -40,6 +40,8 @@ typedef struct _column_info {
gchar **col_title; /* Column titles */
gchar **col_data; /* Column data */
gchar **col_buf; /* Buffer into which to copy data for column */
+ gchar **col_expr; /* Filter expression */
+ gchar **col_expr_val; /* Value for filter expression */
gboolean writable; /* Are we stil writing to the columns? */
} column_info;
diff --git a/gtk/keys.h b/gtk/keys.h
index 2c563a827b..d4686fe9a9 100644
--- a/gtk/keys.h
+++ b/gtk/keys.h
@@ -1,7 +1,7 @@
/* keys.h
* Key definitions for various objects
*
- * $Id: keys.h,v 1.11 2000/08/20 21:55:57 deniel Exp $
+ * $Id: keys.h,v 1.12 2002/01/11 08:21:02 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
@@ -32,6 +32,9 @@
#define E_DFILTER_CM_KEY "display_filter_combo"
#define E_DFILTER_FL_KEY "display_filter_list"
#define E_RFILTER_TE_KEY "read_filter_te"
+#define E_MPACKET_LIST_KEY "menu_packet_list"
+#define E_MPACKET_LIST_ROW_KEY "menu_packet_list_row"
+#define E_MPACKET_LIST_COL_KEY "menu_packet_list_col"
#define PRINT_CMD_LB_KEY "printer_command_label"
#define PRINT_CMD_TE_KEY "printer_command_entry"
diff --git a/gtk/main.c b/gtk/main.c
index c59570fbb1..d1ec5fb830 100644
--- a/gtk/main.c
+++ b/gtk/main.c
@@ -1,6 +1,6 @@
/* main.c
*
- * $Id: main.c,v 1.227 2002/01/11 07:40:31 guy Exp $
+ * $Id: main.c,v 1.228 2002/01/11 08:21:02 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
@@ -222,25 +222,310 @@ set_fonts(GdkFont *regular, GdkFont *bold)
/* Match selected byte pattern */
void
-match_selected_cb(GtkWidget *w, gpointer data)
+match_selected_cb_do(gpointer data, int action, gchar *text)
{
- char *buf;
+ char *ptr;
GtkWidget *filter_te;
- filter_te = gtk_object_get_data(GTK_OBJECT(w), E_DFILTER_TE_KEY);
+ if (!text)
+ return;
+ g_assert(data);
+ filter_te = gtk_object_get_data(GTK_OBJECT(data), E_DFILTER_TE_KEY);
+ g_assert(filter_te);
- buf = proto_alloc_dfilter_string(finfo_selected, cfile.pd);
+ ptr = gtk_entry_get_text(GTK_ENTRY(filter_te));
+
+ switch (action&MATCH_SELECTED_MASK) {
+
+ case MATCH_SELECTED_REPLACE:
+ ptr = text;
+ break;
+
+ case MATCH_SELECTED_AND:
+ if ((!ptr) || (0 == strlen(ptr)))
+ ptr = text;
+ else
+ ptr = g_strconcat("(", ptr, ") && (", text, ")", NULL);
+ break;
+
+ case MATCH_SELECTED_OR:
+ if ((!ptr) || (0 == strlen(ptr)))
+ ptr = text;
+ else
+ ptr = g_strconcat("(", ptr, ") || (", text, ")", NULL);
+ break;
+
+ case MATCH_SELECTED_NOT:
+ ptr = g_strconcat("!(", text, ")", NULL);
+ break;
+
+ case MATCH_SELECTED_AND_NOT:
+ if ((!ptr) || (0 == strlen(ptr)))
+ ptr = g_strconcat("!(", text, ")", NULL);
+ else
+ ptr = g_strconcat("(", ptr, ") && !(", text, ")", NULL);
+ break;
+
+ case MATCH_SELECTED_OR_NOT:
+ if ((!ptr) || (0 == strlen(ptr)))
+ ptr = g_strconcat("!(", text, ")", NULL);
+ else
+ ptr = g_strconcat("(", ptr, ") || !(", text, ")", NULL);
+ break;
+
+ default:
+ break;
+ }
/* create a new one and set the display filter entry accordingly */
- gtk_entry_set_text(GTK_ENTRY(filter_te), buf);
+ gtk_entry_set_text(GTK_ENTRY(filter_te), ptr);
/* Run the display filter so it goes in effect. */
- filter_packets(&cfile, buf);
+ if (action&MATCH_SELECTED_APPLY_NOW)
+ filter_packets(&cfile, ptr);
+
+ /* Don't g_free(text) here. filter_packets() will do it the next time
+ it's called. */
+ /* XXX - what about ptr? */
+}
+
+void
+match_selected_cb_replace(GtkWidget *w, gpointer data)
+{
+ if (finfo_selected)
+ match_selected_cb_do((data ? data : w),
+ MATCH_SELECTED_REPLACE|MATCH_SELECTED_APPLY_NOW,
+ proto_alloc_dfilter_string(finfo_selected, cfile.pd));
+}
+
+void
+match_selected_cb_and(GtkWidget *w, gpointer data)
+{
+ if (finfo_selected)
+ match_selected_cb_do((data ? data : w),
+ MATCH_SELECTED_AND|MATCH_SELECTED_APPLY_NOW,
+ proto_alloc_dfilter_string(finfo_selected, cfile.pd));
+}
+
+void
+match_selected_cb_or(GtkWidget *w, gpointer data)
+{
+ if (finfo_selected)
+ match_selected_cb_do((data ? data : w),
+ MATCH_SELECTED_OR|MATCH_SELECTED_APPLY_NOW,
+ proto_alloc_dfilter_string(finfo_selected, cfile.pd));
+}
+
+void
+match_selected_cb_not(GtkWidget *w, gpointer data)
+{
+ if (finfo_selected)
+ match_selected_cb_do((data ? data : w),
+ MATCH_SELECTED_NOT|MATCH_SELECTED_APPLY_NOW,
+ proto_alloc_dfilter_string(finfo_selected, cfile.pd));
+}
+
+void
+match_selected_cb_and_not(GtkWidget *w, gpointer data)
+{
+ if (finfo_selected)
+ match_selected_cb_do((data ? data : w),
+ MATCH_SELECTED_AND_NOT|MATCH_SELECTED_APPLY_NOW,
+ proto_alloc_dfilter_string(finfo_selected, cfile.pd));
+}
+
+void
+match_selected_cb_or_not(GtkWidget *w, gpointer data)
+{
+ if (finfo_selected)
+ match_selected_cb_do((data ? data : w),
+ MATCH_SELECTED_OR_NOT,
+ proto_alloc_dfilter_string(finfo_selected, cfile.pd));
+}
+
+void
+prepare_selected_cb_replace(GtkWidget *w, gpointer data)
+{
+ if (finfo_selected)
+ match_selected_cb_do((data ? data : w),
+ MATCH_SELECTED_REPLACE,
+ proto_alloc_dfilter_string(finfo_selected, cfile.pd));
+}
+
+void
+prepare_selected_cb_and(GtkWidget *w, gpointer data)
+{
+ if (finfo_selected)
+ match_selected_cb_do((data ? data : w),
+ MATCH_SELECTED_AND,
+ proto_alloc_dfilter_string(finfo_selected, cfile.pd));
+}
+
+void
+prepare_selected_cb_or(GtkWidget *w, gpointer data)
+{
+ if (finfo_selected)
+ match_selected_cb_do((data ? data : w),
+ MATCH_SELECTED_OR,
+ proto_alloc_dfilter_string(finfo_selected, cfile.pd));
+}
+
+void
+prepare_selected_cb_not(GtkWidget *w, gpointer data)
+{
+ if (finfo_selected)
+ match_selected_cb_do((data ? data : w),
+ MATCH_SELECTED_NOT,
+ proto_alloc_dfilter_string(finfo_selected, cfile.pd));
+}
- /* Don't g_free(buf) here. filter_packets() will do it the next time it's called */
+void
+prepare_selected_cb_and_not(GtkWidget *w, gpointer data)
+{
+ if (finfo_selected)
+ match_selected_cb_do((data ? data : w),
+ MATCH_SELECTED_AND_NOT,
+ proto_alloc_dfilter_string(finfo_selected, cfile.pd));
+}
+
+void
+prepare_selected_cb_or_not(GtkWidget *w, gpointer data)
+{
+ if (finfo_selected)
+ match_selected_cb_do((data ? data : w),
+ MATCH_SELECTED_OR_NOT,
+ proto_alloc_dfilter_string(finfo_selected, cfile.pd));
+}
+
+static gchar *
+get_text_from_packet_list(gpointer data)
+{
+ gint row = (gint)gtk_object_get_data(GTK_OBJECT(data), E_MPACKET_LIST_ROW_KEY);
+ gint column = (gint)gtk_object_get_data(GTK_OBJECT(data), E_MPACKET_LIST_COL_KEY);
+ frame_data *fdata = (frame_data *)gtk_clist_get_row_data(GTK_CLIST(packet_list), row);
+ epan_dissect_t *edt;
+ gchar *buf=NULL;
+ int len;
+
+ if (fdata != NULL) {
+ wtap_seek_read(cfile.wth, fdata->file_off, &cfile.pseudo_header,
+ cfile.pd, fdata->cap_len);
+
+ edt = epan_dissect_new(FALSE, FALSE);
+ epan_dissect_run(edt, &cfile.pseudo_header, cfile.pd, fdata,
+ &cfile.cinfo);
+ epan_dissect_fill_in_columns(edt);
+
+ if (strlen(cfile.cinfo.col_expr[column]) != 0 &&
+ strlen(cfile.cinfo.col_expr_val[column]) != 0) {
+ len = strlen(cfile.cinfo.col_expr[column]) +
+ strlen(cfile.cinfo.col_expr_val[column]) + 5;
+ buf = g_malloc0(len);
+ snprintf(buf, len, "%s == %s", cfile.cinfo.col_expr[column],
+ cfile.cinfo.col_expr_val[column]);
+ }
+
+ epan_dissect_free(edt);
+ }
+
+ return buf;
+}
+
+void
+match_selected_cb_replace2(GtkWidget *w, gpointer data)
+{
+ match_selected_cb_do(data,
+ MATCH_SELECTED_REPLACE|MATCH_SELECTED_APPLY_NOW,
+ get_text_from_packet_list(data));
+}
+
+void
+match_selected_cb_and2(GtkWidget *w, gpointer data)
+{
+ match_selected_cb_do(data,
+ MATCH_SELECTED_AND|MATCH_SELECTED_APPLY_NOW,
+ get_text_from_packet_list(data));
+}
+
+void
+match_selected_cb_or2(GtkWidget *w, gpointer data)
+{
+ match_selected_cb_do(data,
+ MATCH_SELECTED_OR|MATCH_SELECTED_APPLY_NOW,
+ get_text_from_packet_list(data));
+}
+
+void
+match_selected_cb_not2(GtkWidget *w, gpointer data)
+{
+ match_selected_cb_do(data,
+ MATCH_SELECTED_NOT|MATCH_SELECTED_APPLY_NOW,
+ get_text_from_packet_list(data));
+}
+
+void
+match_selected_cb_and_not2(GtkWidget *w, gpointer data)
+{
+ match_selected_cb_do(data,
+ MATCH_SELECTED_AND_NOT|MATCH_SELECTED_APPLY_NOW,
+ get_text_from_packet_list(data));
+}
+
+void
+match_selected_cb_or_not2(GtkWidget *w, gpointer data)
+{
+ match_selected_cb_do(data,
+ MATCH_SELECTED_OR_NOT|MATCH_SELECTED_APPLY_NOW,
+ get_text_from_packet_list(data));
}
+void
+prepare_selected_cb_replace2(GtkWidget *w, gpointer data)
+{
+ match_selected_cb_do(data,
+ MATCH_SELECTED_REPLACE,
+ get_text_from_packet_list(data));
+}
+void
+prepare_selected_cb_and2(GtkWidget *w, gpointer data)
+{
+ match_selected_cb_do(data,
+ MATCH_SELECTED_AND,
+ get_text_from_packet_list(data));
+}
+
+void
+prepare_selected_cb_or2(GtkWidget *w, gpointer data)
+{
+ match_selected_cb_do(data,
+ MATCH_SELECTED_OR,
+ get_text_from_packet_list(data));
+}
+
+void
+prepare_selected_cb_not2(GtkWidget *w, gpointer data)
+{
+ match_selected_cb_do(data,
+ MATCH_SELECTED_NOT,
+ get_text_from_packet_list(data));
+}
+
+void
+prepare_selected_cb_and_not2(GtkWidget *w, gpointer data)
+{
+ match_selected_cb_do(data,
+ MATCH_SELECTED_AND_NOT,
+ get_text_from_packet_list(data));
+}
+
+void
+prepare_selected_cb_or_not2(GtkWidget *w, gpointer data)
+{
+ match_selected_cb_do(data,
+ MATCH_SELECTED_OR_NOT,
+ get_text_from_packet_list(data));
+}
/* Run the current display filter on the current packet set, and
redisplay. */
@@ -251,8 +536,10 @@ filter_activate_cb(GtkWidget *w, gpointer data)
GList *filter_list = gtk_object_get_data(GTK_OBJECT(w), E_DFILTER_FL_KEY);
GList *li, *nl = NULL;
gboolean add_filter = TRUE;
+ char *s = NULL;
- char *s = gtk_entry_get_text(GTK_ENTRY(w));
+ g_assert(data);
+ s = gtk_entry_get_text(GTK_ENTRY(data));
/* GtkCombos don't let us get at their list contents easily, so we maintain
our own filter list, and feed it to gtk_combo_set_popdown_strings when
@@ -287,7 +574,6 @@ filter_reset_cb(GtkWidget *w, gpointer data)
if ((filter_te = gtk_object_get_data(GTK_OBJECT(w), E_DFILTER_TE_KEY))) {
gtk_entry_set_text(GTK_ENTRY(filter_te), "");
}
-
filter_packets(&cfile, NULL);
}
@@ -1457,6 +1743,8 @@ main(int argc, char *argv[])
cfile.cinfo.col_buf[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_INFO_LEN);
else
cfile.cinfo.col_buf[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_LEN);
+ cfile.cinfo.col_expr[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_LEN);
+ cfile.cinfo.col_expr_val[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_LEN);
}
#ifdef HAVE_LIBPCAP
@@ -1872,6 +2160,7 @@ create_main_window (gint pl_size, gint tv_size, gint bv_size, e_prefs *prefs)
GtkWidget *main_vbox, *menubar, *u_pane, *l_pane,
*stat_hbox, *column_lb,
*filter_bt, *filter_cm, *filter_te,
+ *filter_apply,
*filter_reset;
GList *filter_list = NULL;
GtkAccelGroup *accel;
@@ -2016,24 +2305,45 @@ create_main_window (gint pl_size, gint tv_size, gint bv_size, e_prefs *prefs)
gtk_object_set_data(GTK_OBJECT(filter_te), E_DFILTER_FL_KEY, filter_list);
gtk_box_pack_start(GTK_BOX(stat_hbox), filter_cm, TRUE, TRUE, 3);
gtk_signal_connect(GTK_OBJECT(filter_te), "activate",
- GTK_SIGNAL_FUNC(filter_activate_cb), (gpointer) NULL);
+ GTK_SIGNAL_FUNC(filter_activate_cb), filter_te);
gtk_widget_show(filter_cm);
filter_reset = gtk_button_new_with_label("Reset");
gtk_object_set_data(GTK_OBJECT(filter_reset), E_DFILTER_TE_KEY, filter_te);
gtk_signal_connect(GTK_OBJECT(filter_reset), "clicked",
- GTK_SIGNAL_FUNC(filter_reset_cb), (gpointer) NULL);
+ GTK_SIGNAL_FUNC(filter_reset_cb), NULL);
gtk_box_pack_start(GTK_BOX(stat_hbox), filter_reset, FALSE, TRUE, 1);
gtk_widget_show(filter_reset);
+ filter_apply = gtk_button_new_with_label("Apply");
+ gtk_object_set_data(GTK_OBJECT(filter_apply), E_DFILTER_CM_KEY, filter_cm);
+ gtk_object_set_data(GTK_OBJECT(filter_apply), E_DFILTER_FL_KEY, filter_list);
+ gtk_signal_connect(GTK_OBJECT(filter_apply), "clicked",
+ GTK_SIGNAL_FUNC(filter_activate_cb), filter_te);
+ gtk_box_pack_start(GTK_BOX(stat_hbox), filter_apply, FALSE, TRUE, 1);
+ gtk_widget_show(filter_apply);
+
/* Sets the text entry widget pointer as the E_DILTER_TE_KEY data
* of any widget that ends up calling a callback which needs
* that text entry pointer */
set_menu_object_data("/File/Open...", E_DFILTER_TE_KEY, filter_te);
set_menu_object_data("/File/Reload", E_DFILTER_TE_KEY, filter_te);
set_menu_object_data("/Edit/Filters...", E_FILT_TE_PTR_KEY, filter_te);
- set_menu_object_data("/Display/Match Selected", E_DFILTER_TE_KEY, filter_te);
set_menu_object_data("/Tools/Follow TCP Stream", E_DFILTER_TE_KEY, filter_te);
+ set_menu_object_data("/Display/Match/Selected", E_DFILTER_TE_KEY, filter_te);
+ set_menu_object_data("/Display/Match/Not Selected", E_DFILTER_TE_KEY, filter_te);
+ set_menu_object_data("/Display/Match/And Selected", E_DFILTER_TE_KEY, filter_te);
+ set_menu_object_data("/Display/Match/Or Selected", E_DFILTER_TE_KEY, filter_te);
+ set_menu_object_data("/Display/Match/And Not Selected", E_DFILTER_TE_KEY, filter_te);
+ set_menu_object_data("/Display/Match/Or Not Selected", E_DFILTER_TE_KEY, filter_te);
+ set_menu_object_data("/Display/Prepare/Selected", E_DFILTER_TE_KEY, filter_te);
+ set_menu_object_data("/Display/Prepare/Not Selected", E_DFILTER_TE_KEY, filter_te);
+ set_menu_object_data("/Display/Prepare/And Selected", E_DFILTER_TE_KEY, filter_te);
+ set_menu_object_data("/Display/Prepare/Or Selected", E_DFILTER_TE_KEY, filter_te);
+ set_menu_object_data("/Display/Prepare/And Not Selected", E_DFILTER_TE_KEY, filter_te);
+ set_menu_object_data("/Display/Prepare/Or Not Selected", E_DFILTER_TE_KEY, filter_te);
+ gtk_object_set_data(GTK_OBJECT(popup_menu_object), E_DFILTER_TE_KEY, filter_te);
+ gtk_object_set_data(GTK_OBJECT(popup_menu_object), E_MPACKET_LIST_KEY, packet_list);
info_bar = gtk_statusbar_new();
main_ctx = gtk_statusbar_get_context_id(GTK_STATUSBAR(info_bar), "main");
diff --git a/gtk/main.h b/gtk/main.h
index 65662d3bd0..363a8340fa 100644
--- a/gtk/main.h
+++ b/gtk/main.h
@@ -1,7 +1,7 @@
/* main.h
* Global defines, etc.
*
- * $Id: main.h,v 1.25 2001/12/31 04:41:50 gerald Exp $
+ * $Id: main.h,v 1.26 2002/01/11 08:21:02 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
@@ -43,6 +43,16 @@
#define DEF_READY_MESSAGE " Ready to load file"
#endif
+#define MATCH_SELECTED_REPLACE 0
+#define MATCH_SELECTED_AND 1
+#define MATCH_SELECTED_OR 2
+#define MATCH_SELECTED_NOT 3
+#define MATCH_SELECTED_AND_NOT 4
+#define MATCH_SELECTED_OR_NOT 5
+
+#define MATCH_SELECTED_MASK 0x0ff
+#define MATCH_SELECTED_APPLY_NOW 0x100
+
typedef struct _selection_info {
GtkWidget *tree;
GtkWidget *text;
@@ -51,7 +61,30 @@ typedef struct _selection_info {
extern GtkStyle *item_style;
void about_ethereal( GtkWidget *, gpointer);
-void match_selected_cb( GtkWidget *, gpointer);
+void match_selected_cb_replace( GtkWidget *, gpointer);
+void match_selected_cb_and( GtkWidget *, gpointer);
+void match_selected_cb_or( GtkWidget *, gpointer);
+void match_selected_cb_not( GtkWidget *, gpointer);
+void match_selected_cb_and_not( GtkWidget *, gpointer);
+void match_selected_cb_or_not( GtkWidget *, gpointer);
+void prepare_selected_cb_replace( GtkWidget *, gpointer);
+void prepare_selected_cb_and( GtkWidget *, gpointer);
+void prepare_selected_cb_or( GtkWidget *, gpointer);
+void prepare_selected_cb_not( GtkWidget *, gpointer);
+void prepare_selected_cb_and_not( GtkWidget *, gpointer);
+void prepare_selected_cb_or_not( GtkWidget *, gpointer);
+void match_selected_cb_replace2( GtkWidget *, gpointer);
+void match_selected_cb_and2( GtkWidget *, gpointer);
+void match_selected_cb_or2( GtkWidget *, gpointer);
+void match_selected_cb_not2( GtkWidget *, gpointer);
+void match_selected_cb_and_not2( GtkWidget *, gpointer);
+void match_selected_cb_or_not2( GtkWidget *, gpointer);
+void prepare_selected_cb_replace2( GtkWidget *, gpointer);
+void prepare_selected_cb_and2( GtkWidget *, gpointer);
+void prepare_selected_cb_or2( GtkWidget *, gpointer);
+void prepare_selected_cb_not2( GtkWidget *, gpointer);
+void prepare_selected_cb_and_not2( GtkWidget *, gpointer);
+void prepare_selected_cb_or_not2( GtkWidget *, gpointer);
void file_quit_cmd_cb(GtkWidget *, gpointer);
void file_print_cmd_cb(GtkWidget *, gpointer);
void file_print_packet_cmd_cb(GtkWidget *, gpointer);
diff --git a/gtk/menu.c b/gtk/menu.c
index d9cf44cbd6..76e8e579af 100644
--- a/gtk/menu.c
+++ b/gtk/menu.c
@@ -1,7 +1,7 @@
/* menu.c
* Menu routines
*
- * $Id: menu.c,v 1.59 2002/01/11 07:40:31 guy Exp $
+ * $Id: menu.c,v 1.60 2002/01/11 08:21:02 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
@@ -141,7 +141,20 @@ static GtkItemFactoryEntry menu_items[] =
#endif /* HAVE_LIBPCAP */
{"/_Display", NULL, NULL, 0, "<Branch>" },
{"/Display/_Options...", NULL, GTK_MENU_FUNC(display_opt_cb), 0, NULL},
- {"/Display/_Match Selected", NULL, GTK_MENU_FUNC(match_selected_cb), 0, NULL},
+ {"/Display/_Match", NULL, NULL, 0, "<Branch>" },
+ {"/Display/Match/_Selected", NULL, GTK_MENU_FUNC(match_selected_cb_replace), 0, NULL},
+ {"/Display/Match/_Not Selected", NULL, GTK_MENU_FUNC(match_selected_cb_not), 0, NULL},
+ {"/Display/Match/_And Selected", NULL, GTK_MENU_FUNC(match_selected_cb_and), 0, NULL},
+ {"/Display/Match/_Or Selected", NULL, GTK_MENU_FUNC(match_selected_cb_or), 0, NULL},
+ {"/Display/Match/A_nd Not Selected", NULL, GTK_MENU_FUNC(match_selected_cb_and_not), 0, NULL},
+ {"/Display/Match/O_r Not Selected", NULL, GTK_MENU_FUNC(match_selected_cb_or_not), 0, NULL},
+ {"/Display/_Prepare", NULL, NULL, 0, "<Branch>" },
+ {"/Display/Prepare/_Selected", NULL, GTK_MENU_FUNC(prepare_selected_cb_replace), 0, NULL},
+ {"/Display/Prepare/_Not Selected", NULL, GTK_MENU_FUNC(prepare_selected_cb_not), 0, NULL},
+ {"/Display/Prepare/_And Selected", NULL, GTK_MENU_FUNC(prepare_selected_cb_and), 0, NULL},
+ {"/Display/Prepare/_Or Selected", NULL, GTK_MENU_FUNC(prepare_selected_cb_or), 0, NULL},
+ {"/Display/Prepare/A_nd Not Selected", NULL, GTK_MENU_FUNC(prepare_selected_cb_and_not), 0, NULL},
+ {"/Display/Prepare/O_r Not Selected", NULL, GTK_MENU_FUNC(prepare_selected_cb_or_not), 0, NULL},
{"/Display/_Colorize Display...", NULL, GTK_MENU_FUNC(color_display_cb), 0, NULL},
{"/Display/Collapse _All", NULL, GTK_MENU_FUNC(collapse_all_cb), 0, NULL},
{"/Display/_Expand All", NULL, GTK_MENU_FUNC(expand_all_cb), 0, NULL},
@@ -178,6 +191,20 @@ static GtkItemFactoryEntry packet_list_menu_items[] =
{"/Display Filters...", NULL, GTK_MENU_FUNC(dfilter_dialog_cb), 0, NULL},
{"/<separator>", NULL, NULL, 0, "<Separator>"},
{"/Mark Frame", NULL, GTK_MENU_FUNC(mark_frame_cb), 0, NULL},
+ {"/Match", NULL, NULL, 0, "<Branch>" },
+ {"/Match/_Selected", NULL, GTK_MENU_FUNC(match_selected_cb_replace2), 0, NULL},
+ {"/Match/_Not Selected", NULL, GTK_MENU_FUNC(match_selected_cb_not2), 0, NULL},
+ {"/Match/_And Selected", NULL, GTK_MENU_FUNC(match_selected_cb_and2), 0, NULL},
+ {"/Match/_Or Selected", NULL, GTK_MENU_FUNC(match_selected_cb_or2), 0, NULL},
+ {"/Match/A_nd Not Selected", NULL, GTK_MENU_FUNC(match_selected_cb_and_not2), 0, NULL},
+ {"/Match/O_r Not Selected", NULL, GTK_MENU_FUNC(match_selected_cb_or_not2), 0, NULL},
+ {"/Prepare", NULL, NULL, 0, "<Branch>" },
+ {"/Prepare/_Selected", NULL, GTK_MENU_FUNC(prepare_selected_cb_replace2), 0, NULL},
+ {"/Prepare/_Not Selected", NULL, GTK_MENU_FUNC(prepare_selected_cb_not2), 0, NULL},
+ {"/Prepare/_And Selected", NULL, GTK_MENU_FUNC(prepare_selected_cb_and2), 0, NULL},
+ {"/Prepare/_Or Selected", NULL, GTK_MENU_FUNC(prepare_selected_cb_or2), 0, NULL},
+ {"/Prepare/A_nd Not Selected", NULL, GTK_MENU_FUNC(prepare_selected_cb_and_not2), 0, NULL},
+ {"/Prepare/O_r Not Selected", NULL, GTK_MENU_FUNC(prepare_selected_cb_or_not2), 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},
@@ -193,7 +220,20 @@ static GtkItemFactoryEntry tree_view_menu_items[] =
{"/<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},
- {"/Match Selected", NULL, GTK_MENU_FUNC(match_selected_cb), 0, NULL},
+ {"/Match", NULL, NULL, 0, "<Branch>" },
+ {"/Match/_Selected", NULL, GTK_MENU_FUNC(match_selected_cb_replace), 0, NULL},
+ {"/Match/_Not Selected", NULL, GTK_MENU_FUNC(match_selected_cb_not), 0, NULL},
+ {"/Match/_And Selected", NULL, GTK_MENU_FUNC(match_selected_cb_and), 0, NULL},
+ {"/Match/_Or Selected", NULL, GTK_MENU_FUNC(match_selected_cb_or), 0, NULL},
+ {"/Match/A_nd Not Selected", NULL, GTK_MENU_FUNC(match_selected_cb_and_not), 0, NULL},
+ {"/Match/O_r Not Selected", NULL, GTK_MENU_FUNC(match_selected_cb_or_not), 0, NULL},
+ {"/Prepare", NULL, NULL, 0, "<Branch>" },
+ {"/Prepare/_Selected", NULL, GTK_MENU_FUNC(prepare_selected_cb_replace), 0, NULL},
+ {"/Prepare/_Not Selected", NULL, GTK_MENU_FUNC(prepare_selected_cb_not), 0, NULL},
+ {"/Prepare/_And Selected", NULL, GTK_MENU_FUNC(prepare_selected_cb_and), 0, NULL},
+ {"/Prepare/_Or Selected", NULL, GTK_MENU_FUNC(prepare_selected_cb_or), 0, NULL},
+ {"/Prepare/A_nd Not Selected", NULL, GTK_MENU_FUNC(prepare_selected_cb_and_not), 0, NULL},
+ {"/Prepare/O_r Not Selected", NULL, GTK_MENU_FUNC(prepare_selected_cb_or_not), 0, NULL},
{"/<separator>", NULL, NULL, 0, "<Separator>"},
{"/Collapse All", NULL, GTK_MENU_FUNC(collapse_all_cb), 0, NULL},
{"/Expand All", NULL, GTK_MENU_FUNC(expand_all_cb), 0, NULL}
@@ -242,17 +282,17 @@ menus_init(void) {
/* popup */
packet_list_menu_factory = gtk_item_factory_new(GTK_TYPE_MENU, "<main>", NULL);
- gtk_item_factory_create_items_ac(packet_list_menu_factory, sizeof(packet_list_menu_items)/sizeof(packet_list_menu_items[0]), packet_list_menu_items, NULL, 2);
+ gtk_item_factory_create_items_ac(packet_list_menu_factory, sizeof(packet_list_menu_items)/sizeof(packet_list_menu_items[0]), packet_list_menu_items, popup_menu_object, 2);
gtk_object_set_data(GTK_OBJECT(popup_menu_object), PM_PACKET_LIST_KEY, packet_list_menu_factory->widget);
popup_menu_list = g_slist_append((GSList *)popup_menu_list, packet_list_menu_factory);
tree_view_menu_factory = gtk_item_factory_new(GTK_TYPE_MENU, "<main>", NULL);
- gtk_item_factory_create_items_ac(tree_view_menu_factory, sizeof(tree_view_menu_items)/sizeof(tree_view_menu_items[0]), tree_view_menu_items, NULL, 2);
+ gtk_item_factory_create_items_ac(tree_view_menu_factory, sizeof(tree_view_menu_items)/sizeof(tree_view_menu_items[0]), tree_view_menu_items, popup_menu_object, 2);
gtk_object_set_data(GTK_OBJECT(popup_menu_object), PM_TREE_VIEW_KEY, tree_view_menu_factory->widget);
popup_menu_list = g_slist_append((GSList *)popup_menu_list, tree_view_menu_factory);
hexdump_menu_factory = gtk_item_factory_new(GTK_TYPE_MENU, "<main>", NULL);
- gtk_item_factory_create_items_ac(hexdump_menu_factory, sizeof(hexdump_menu_items)/sizeof(hexdump_menu_items[0]), hexdump_menu_items, NULL, 2);
+ gtk_item_factory_create_items_ac(hexdump_menu_factory, sizeof(hexdump_menu_items)/sizeof(hexdump_menu_items[0]), hexdump_menu_items, popup_menu_object, 2);
gtk_object_set_data(GTK_OBJECT(popup_menu_object), PM_HEXDUMP_KEY, hexdump_menu_factory->widget);
popup_menu_list = g_slist_append((GSList *)popup_menu_list, hexdump_menu_factory);
@@ -282,18 +322,40 @@ set_menu_sensitivity_meat(GtkItemFactory *ifactory, gchar *path, gint val) {
}
}
+/* Enable/disable menu sensitivity */
+/* /menu/path - old functionality */
+/* <MenuName>/menu/path - new functionality */
+/* MenuName: <Main>, <PacketList>, <TreeView>, <HexDump> */
static void
set_menu_sensitivity (gchar *path, gint val) {
GSList *menu_list = popup_menu_list;
- gchar *shortpath = strrchr(path, '/');
-
- set_menu_sensitivity_meat(factory, path, val);
-
- while (menu_list != NULL) {
- set_menu_sensitivity_meat(menu_list->data, shortpath, val);
- menu_list = g_slist_next(menu_list);
+ gchar *prefix;
+ gchar *shortpath;
+
+ if ('<' == *path) {
+ /* New functionality => selective enable/disable per menu */
+ prefix=strchr(path, '/');
+ shortpath=strrchr(prefix, '/');
+
+ if (0 == strncmp(path, "<Main>", 6))
+ set_menu_sensitivity_meat(factory, prefix, val);
+ else if (0 == strncmp(path, "<PacketList>", 12))
+ set_menu_sensitivity_meat(packet_list_menu_factory, shortpath, val);
+ else if (0 == strncmp(path, "<TreeView>", 10))
+ set_menu_sensitivity_meat(tree_view_menu_factory, shortpath, val);
+ else if (0 == strncmp(path, "<HexDump>", 9))
+ set_menu_sensitivity_meat(hexdump_menu_factory, shortpath, val);
+ } else {
+ /* Old functionality => enable/disable all menus with same shortpath */
+ shortpath = strrchr(path, '/');
+
+ set_menu_sensitivity_meat(factory, path, val);
+
+ while (menu_list != NULL) {
+ set_menu_sensitivity_meat(menu_list->data, shortpath, val);
+ menu_list = g_slist_next(menu_list);
+ }
}
-
}
void
@@ -322,6 +384,8 @@ popup_menu_handler(GtkWidget *widget, GdkEvent *event, gpointer data)
{
GtkWidget *menu = NULL;
GdkEventButton *event_button = NULL;
+ GtkCList *packet_list = NULL;
+ gint row, column;
if(widget == NULL || event == NULL || data == NULL) {
return FALSE;
@@ -334,6 +398,19 @@ popup_menu_handler(GtkWidget *widget, GdkEvent *event, gpointer data)
* I guess, like a CList with one column(?) and the expander widget
* as a pixmap.
*/
+ /* Check if we are on packet_list object */
+ if (widget == gtk_object_get_data(GTK_OBJECT(popup_menu_object),
+ E_MPACKET_LIST_KEY)) {
+ packet_list=GTK_CLIST(widget);
+ if (gtk_clist_get_selection_info(GTK_CLIST(packet_list),
+ ((GdkEventButton *)event)->x,
+ ((GdkEventButton *)event)->y,&row,&column)) {
+ gtk_object_set_data(GTK_OBJECT(popup_menu_object),
+ E_MPACKET_LIST_ROW_KEY, (gpointer *)row);
+ gtk_object_set_data(GTK_OBJECT(popup_menu_object),
+ E_MPACKET_LIST_COL_KEY, (gpointer *)column);
+ }
+ }
menu = (GtkWidget *)data;
if(event->type == GDK_BUTTON_PRESS) {
event_button = (GdkEventButton *) event;
@@ -392,6 +469,8 @@ set_menus_for_captured_packets(gboolean have_captured_packets)
set_menu_sensitivity("/Display/Colorize Display...", have_captured_packets);
set_menu_sensitivity("/Tools/Summary", have_captured_packets);
set_menu_sensitivity("/Tools/Protocol Hierarchy Statistics", have_captured_packets);
+ set_menu_sensitivity("<PacketList>/Display/Match", have_captured_packets);
+ set_menu_sensitivity("<PacketList>/Display/Prepare", have_captured_packets);
}
/* Enable or disable menu items based on whether a packet is selected. */
@@ -416,7 +495,7 @@ set_menus_for_selected_packet(gboolean have_selected_packet)
}
/* Enable or disable menu items based on whether a tree row is selected
- and and on whether a "Match Selected" can be done. */
+ and and on whether a "Match" can be done. */
void
set_menus_for_selected_tree_row(gboolean have_selected_tree)
{
@@ -429,10 +508,20 @@ set_menus_for_selected_tree_row(gboolean have_selected_tree)
} else {
properties = prefs_is_registered_protocol(proto_registrar_get_abbrev(hfinfo->parent));
}
- set_menu_sensitivity("/Display/Match Selected",
+ set_menu_sensitivity("<Main>/Display/Match",
+ proto_can_match_selected(finfo_selected));
+ set_menu_sensitivity("<TreeView>/Display/Match",
+ proto_can_match_selected(finfo_selected));
+ set_menu_sensitivity("<Main>/Display/Prepare",
proto_can_match_selected(finfo_selected));
- } else
- set_menu_sensitivity("/Display/Match Selected", FALSE);
+ set_menu_sensitivity("<TreeView>/Display/Prepare",
+ proto_can_match_selected(finfo_selected));
+ } else {
+ set_menu_sensitivity("<Main>/Display/Match", FALSE);
+ set_menu_sensitivity("<TreeView>/Display/Match", FALSE);
+ set_menu_sensitivity("<Main>/Display/Prepare", FALSE);
+ set_menu_sensitivity("<TreeView>/Display/Prepare", FALSE);
+ }
set_menu_sensitivity("/Protocol Properties...", have_selected_tree && properties);
}