aboutsummaryrefslogtreecommitdiffstats
path: root/ui/gtk/conversations_table.c
diff options
context:
space:
mode:
authorJörg Mayer <jmayer@loplof.de>2012-01-15 21:59:11 +0000
committerJörg Mayer <jmayer@loplof.de>2012-01-15 21:59:11 +0000
commitbe706c63801fb98d42fb743b27b16cc36273651e (patch)
tree62ed0b552191eb0753d26a3edcbab73459a15f7f /ui/gtk/conversations_table.c
parent6d69ef093cd6868ab51f8b52477a510172033353 (diff)
Move gtk to ui/gtk.
This looses the last checkin to gtk, will add this manually back. svn path=/trunk/; revision=40518
Diffstat (limited to 'ui/gtk/conversations_table.c')
-rw-r--r--ui/gtk/conversations_table.c3016
1 files changed, 3016 insertions, 0 deletions
diff --git a/ui/gtk/conversations_table.c b/ui/gtk/conversations_table.c
new file mode 100644
index 0000000000..5573b8162a
--- /dev/null
+++ b/ui/gtk/conversations_table.c
@@ -0,0 +1,3016 @@
+/* conversations_table.c
+ * conversations_table 2003 Ronnie Sahlberg
+ * Helper routines common to all endpoint conversations tap.
+ *
+ * $Id$
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.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.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <string.h>
+#include <locale.h>
+
+#include <gtk/gtk.h>
+
+#include <epan/packet_info.h>
+#include <epan/to_str.h>
+#include <epan/address.h>
+#include <epan/addr_resolv.h>
+#include <epan/tap.h>
+#include <epan/nstime.h>
+
+#include "../simple_dialog.h"
+#include "../globals.h"
+
+#include "ui/gtk/sat.h"
+#include "ui/gtk/conversations_table.h"
+#include "ui/gtk/filter_utils.h"
+#include "ui/gtk/gtkglobals.h"
+#include "ui/gtk/gui_utils.h"
+#include "ui/gtk/dlg_utils.h"
+#include "ui/gtk/help_dlg.h"
+#include "ui/gtk/main.h"
+#include "ui/gtk/stock_icons.h"
+#include "ui/gtk/follow_tcp.h"
+#include "ui/gtk/follow_udp.h"
+#include "ui/gtk/keys.h"
+#include "ui/gtk/utf8_entities.h"
+
+#include "old-gtk-compat.h"
+
+#define COL_STR_LEN 16
+#define CONV_PTR_KEY "conversations-pointer"
+#define NB_PAGES_KEY "notebook-pages"
+#define FOLLOW_STREAM_BT_KEY "follow-stream-button"
+#define NO_BPS_STR "N/A"
+
+#define CMP_NUM(n1, n2) \
+ if ((n1) > (n2)) \
+ return 1; \
+ else if ((n1) < (n2)) \
+ return -1; \
+ else \
+ return 0;
+
+/* convert a port number into a string */
+static char *
+ct_port_to_str(int port_type_val, guint32 port)
+{
+ static int i=0;
+ static gchar *strp, str[4][12];
+ gchar *bp;
+
+ strp=str[i];
+
+ switch(port_type_val){
+ case PT_TCP:
+ case PT_UDP:
+ case PT_SCTP:
+ case PT_NCP:
+ i = (i+1)%4;
+ bp = &strp[11];
+
+ *bp = 0;
+ do {
+ *--bp = (port % 10) +'0';
+ } while ((port /= 10) != 0 && bp > strp);
+ return bp;
+ }
+ return NULL;
+}
+
+#define FN_SRC_ADDRESS 0
+#define FN_DST_ADDRESS 1
+#define FN_ANY_ADDRESS 2
+#define FN_SRC_PORT 3
+#define FN_DST_PORT 4
+#define FN_ANY_PORT 5
+/* given an address (to distinguish between ipv4 and ipv6 for tcp/udp),
+ a port_type and a name_type (FN_...)
+ return a string for the filter name.
+
+ Some addresses, like AT_ETHER may actually be any of multiple types
+ of protocols, either ethernet, tokenring, fddi, wlan etc so we must be
+ more specific there; that's why we need specific_addr_type.
+*/
+static const char *
+ct_get_filter_name(address *addr, int specific_addr_type_val, int port_type_val, int name_type_val)
+{
+ switch(name_type_val){
+ case FN_SRC_ADDRESS:
+ switch(addr->type){
+ case AT_ETHER:
+ switch(specific_addr_type_val){
+ case SAT_ETHER:
+ return "eth.src";
+ case SAT_WLAN:
+ return "wlan.sa";
+ case SAT_FDDI:
+ return "fddi.src";
+ case SAT_TOKENRING:
+ return "tr.src";
+ default:
+ break;
+ }
+ break;
+ case AT_IPv4:
+ return "ip.src";
+ case AT_IPv6:
+ return "ipv6.src";
+ case AT_IPX:
+ return "ipx.src";
+ case AT_FC:
+ return "fc.s_id";
+ case AT_URI:
+ switch(specific_addr_type_val){
+ case SAT_JXTA:
+ return "jxta.message.src";
+ default:
+ break;
+ }
+ break;
+ case AT_USB:
+ return "usb.sa";
+ default:
+ break;
+ }
+ break;
+ case FN_DST_ADDRESS:
+ switch(addr->type){
+ case AT_ETHER:
+ switch(specific_addr_type_val){
+ case SAT_ETHER:
+ return "eth.dst";
+ case SAT_WLAN:
+ return "wlan.da";
+ case SAT_FDDI:
+ return "fddi.dst";
+ case SAT_TOKENRING:
+ return "tr.dst";
+ default:
+ break;
+ }
+ break;
+ case AT_IPv4:
+ return "ip.dst";
+ case AT_IPv6:
+ return "ipv6.dst";
+ case AT_IPX:
+ return "ipx.dst";
+ case AT_FC:
+ return "fc.d_id";
+ case AT_URI:
+ switch(specific_addr_type_val){
+ case SAT_JXTA:
+ return "jxta.message.dst";
+ default:
+ break;
+ }
+ break;
+ case AT_USB:
+ return "usb.da";
+ default:
+ break;
+ }
+ break;
+ case FN_ANY_ADDRESS:
+ switch(addr->type){
+ case AT_ETHER:
+ switch(specific_addr_type_val){
+ case SAT_ETHER:
+ return "eth.addr";
+ case SAT_WLAN:
+ return "wlan.addr";
+ case SAT_FDDI:
+ return "fddi.addr";
+ case SAT_TOKENRING:
+ return "tr.addr";
+ default:
+ break;
+ }
+ break;
+ case AT_IPv4:
+ return "ip.addr";
+ case AT_IPv6:
+ return "ipv6.addr";
+ case AT_IPX:
+ return "ipx.addr";
+ case AT_FC:
+ return "fc.id";
+ case AT_URI:
+ switch(specific_addr_type_val){
+ case SAT_JXTA:
+ return "jxta.message.address";
+ default:
+ break;
+ }
+ break;
+ case AT_USB:
+ return "usb.addr";
+ default:
+ break;
+ }
+ break;
+ case FN_SRC_PORT:
+ switch(port_type_val){
+ case PT_TCP:
+ return "tcp.srcport";
+ case PT_UDP:
+ return "udp.srcport";
+ case PT_SCTP:
+ return "sctp.srcport";
+ case PT_NCP:
+ return "ncp.connection";
+ default:
+ break;
+ }
+ break;
+ case FN_DST_PORT:
+ switch(port_type_val){
+ case PT_TCP:
+ return "tcp.dstport";
+ case PT_UDP:
+ return "udp.dstport";
+ case PT_SCTP:
+ return "sctp.dstport";
+ case PT_NCP:
+ return "ncp.connection";
+ default:
+ break;
+ }
+ break;
+ case FN_ANY_PORT:
+ switch(port_type_val){
+ case PT_TCP:
+ return "tcp.port";
+ case PT_UDP:
+ return "udp.port";
+ case PT_SCTP:
+ return "sctp.port";
+ case PT_NCP:
+ return "ncp.connection";
+ default:
+ break;
+ }
+ break;
+ }
+
+ g_assert_not_reached();
+ return NULL;
+}
+
+static void
+reset_ct_table_data(conversations_table *ct)
+{
+ guint32 i;
+ char title[256];
+ GString *error_string;
+ const char *filter;
+ GtkListStore *store;
+
+ if (ct->use_dfilter) {
+ filter = gtk_entry_get_text(GTK_ENTRY(main_display_filter_widget));
+ } else {
+ filter = ct->filter;
+ }
+
+ error_string = set_tap_dfilter (ct, filter);
+ if (error_string) {
+ simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", error_string->str);
+ g_string_free(error_string, TRUE);
+ return;
+ }
+
+ if(ct->page_lb) {
+ g_snprintf(title, sizeof(title), "Conversations: %s", cf_get_display_name(&cfile));
+ gtk_window_set_title(GTK_WINDOW(ct->win), title);
+ g_snprintf(title, sizeof(title), "%s", ct->name);
+ gtk_label_set_text(GTK_LABEL(ct->page_lb), title);
+ gtk_widget_set_sensitive(ct->page_lb, FALSE);
+
+ if (ct->use_dfilter) {
+ if (filter && strlen(filter)) {
+ g_snprintf(title, sizeof(title), "%s Conversations - Filter: %s", ct->name, filter);
+ } else {
+ g_snprintf(title, sizeof(title), "%s Conversations - No Filter", ct->name);
+ }
+ } else {
+ g_snprintf(title, sizeof(title), "%s Conversations", ct->name);
+ }
+ gtk_label_set_text(GTK_LABEL(ct->name_lb), title);
+ } else {
+ g_snprintf(title, sizeof(title), "%s Conversations: %s", ct->name, cf_get_display_name(&cfile));
+ gtk_window_set_title(GTK_WINDOW(ct->win), title);
+ }
+
+ /* remove all entries from the list */
+ store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(ct->table)));
+ gtk_list_store_clear(store);
+
+ /* delete all conversations */
+ for(i=0;i<ct->num_conversations;i++){
+ conv_t *conv = &g_array_index(ct->conversations, conv_t, i);
+ g_free((gpointer)conv->src_address.data);
+ g_free((gpointer)conv->dst_address.data);
+ }
+ if (ct->conversations)
+ g_array_free(ct->conversations, TRUE);
+
+ if (ct->hashtable != NULL)
+ g_hash_table_destroy(ct->hashtable);
+
+ ct->conversations=NULL;
+ ct->hashtable=NULL;
+ ct->num_conversations=0;
+}
+
+static void
+reset_ct_table_data_cb(void *arg)
+{
+ reset_ct_table_data(arg);
+}
+
+static void
+ct_win_destroy_cb(GtkWindow *win _U_, gpointer data)
+{
+ conversations_table *conversations=(conversations_table *)data;
+
+ protect_thread_critical_region();
+ remove_tap_listener(conversations);
+ unprotect_thread_critical_region();
+
+ reset_ct_table_data(conversations);
+ g_free(conversations);
+}
+
+enum
+{
+ SRC_ADR_COLUMN,
+ SRC_PORT_COLUMN,
+ DST_ADR_COLUMN,
+ DST_PORT_COLUMN,
+ PACKETS_COLUMN,
+ BYTES_COLUMN,
+ PKT_AB_COLUMN,
+ BYTES_AB_COLUMN,
+ PKT_BA_COLUMN,
+ BYTES_BA_COLUMN,
+ START_COLUMN,
+ DURATION_COLUMN,
+ BPS_AB_COLUMN,
+ BPS_BA_COLUMN,
+ INDEX_COLUMN,
+ N_COLUMNS
+};
+
+static gint
+ct_sort_func(GtkTreeModel *model,
+ GtkTreeIter *a,
+ GtkTreeIter *b,
+ gpointer user_data)
+{
+ guint32 idx1, idx2;
+ /* The col to get data from is in userdata */
+ gint data_column = GPOINTER_TO_INT(user_data);
+
+ conversations_table *ct = g_object_get_data(G_OBJECT(model), CONV_PTR_KEY);
+ conv_t *conv1 = NULL;
+ conv_t *conv2 = NULL;
+ double duration1, duration2;
+
+ gtk_tree_model_get(model, a, INDEX_COLUMN, &idx1, -1);
+ gtk_tree_model_get(model, b, INDEX_COLUMN, &idx2, -1);
+
+ if (!ct || idx1 >= ct->num_conversations || idx2 >= ct->num_conversations)
+ return 0;
+
+ conv1 = &g_array_index(ct->conversations, conv_t, idx1);
+ conv2 = &g_array_index(ct->conversations, conv_t, idx2);
+
+
+ switch(data_column){
+ case SRC_ADR_COLUMN: /* Source address */
+ return(CMP_ADDRESS(&conv1->src_address, &conv2->src_address));
+ case DST_ADR_COLUMN: /* Destination address */
+ return(CMP_ADDRESS(&conv1->dst_address, &conv2->dst_address));
+ case SRC_PORT_COLUMN: /* Source port */
+ CMP_NUM(conv1->src_port, conv2->src_port);
+ case DST_PORT_COLUMN: /* Destination port */
+ CMP_NUM(conv1->dst_port, conv2->dst_port);
+ case START_COLUMN: /* Start time */
+ return nstime_cmp(&conv1->start_time, &conv2->start_time);
+ }
+
+ duration1 = nstime_to_sec(&conv1->stop_time) - nstime_to_sec(&conv1->start_time);
+ duration2 = nstime_to_sec(&conv2->stop_time) - nstime_to_sec(&conv2->start_time);
+
+ switch(data_column){
+ case DURATION_COLUMN: /* Duration */
+ CMP_NUM(duration1, duration2);
+ case BPS_AB_COLUMN: /* bps A->B */
+ if (duration1 > 0 && conv1->tx_frames > 1 && duration2 > 0 && conv2->tx_frames > 1) {
+ CMP_NUM((gint64) conv1->tx_bytes / duration1, (gint64) conv2->tx_bytes / duration2);
+ } else {
+ CMP_NUM(conv1->tx_bytes, conv2->tx_bytes);
+ }
+ case BPS_BA_COLUMN: /* bps A<-B */
+ if (duration1 > 0 && conv1->rx_frames > 1 && duration2 > 0 && conv2->rx_frames > 1) {
+ CMP_NUM((gint64) conv1->rx_bytes / duration1, (gint64) conv2->rx_bytes / duration2);
+ } else {
+ CMP_NUM(conv1->rx_bytes, conv2->rx_bytes);
+ }
+ default:
+ g_assert_not_reached();
+ }
+
+ return 0;
+}
+
+/* Filter direction */
+#define DIR_A_TO_FROM_B 0
+#define DIR_A_TO_B 1
+#define DIR_A_FROM_B 2
+#define DIR_A_TO_FROM_ANY 3
+#define DIR_A_TO_ANY 4
+#define DIR_A_FROM_ANY 5
+#define DIR_ANY_TO_FROM_B 6
+#define DIR_ANY_FROM_B 7
+#define DIR_ANY_TO_B 8
+
+static void
+ct_select_filter_cb(GtkWidget *widget _U_, gpointer callback_data, guint callback_action)
+{
+ int direction;
+ guint32 idx = 0;
+ conversations_table *ct = (conversations_table *)callback_data;
+ GtkTreeIter iter;
+ GtkTreeModel *model;
+ GtkTreeSelection *sel;
+ char *str = NULL;
+ char *sport, *dport;
+ conv_t *conv;
+
+ direction=FILTER_EXTRA(callback_action);
+
+ sel = gtk_tree_view_get_selection (GTK_TREE_VIEW(ct->table));
+ if (!gtk_tree_selection_get_selected(sel, &model, &iter))
+ return;
+
+ gtk_tree_model_get (model, &iter,
+ INDEX_COLUMN, &idx,
+ -1);
+
+ if(idx>= ct->num_conversations){
+ simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "No conversation selected");
+ return;
+ }
+ conv = &g_array_index(ct->conversations, conv_t, idx);
+ sport=ct_port_to_str(conv->port_type, conv->src_port);
+ dport=ct_port_to_str(conv->port_type, conv->dst_port);
+
+ switch(direction){
+ case DIR_A_TO_FROM_B:
+ /* A <-> B */
+ str = g_strdup_printf("%s==%s%s%s%s%s && %s==%s%s%s%s%s",
+ ct_get_filter_name(&conv->src_address, conv->sat, conv->port_type, FN_ANY_ADDRESS),
+ ep_address_to_str(&conv->src_address),
+ sport?" && ":"",
+ sport?ct_get_filter_name(&conv->src_address, conv->sat, conv->port_type, FN_ANY_PORT):"",
+ sport?"==":"",
+ sport?sport:"",
+ ct_get_filter_name(&conv->dst_address, conv->sat, conv->port_type, FN_ANY_ADDRESS),
+ ep_address_to_str(&conv->dst_address),
+ dport?" && ":"",
+ dport?ct_get_filter_name(&conv->dst_address, conv->sat, conv->port_type, FN_ANY_PORT):"",
+ dport?"==":"",
+ dport?dport:""
+ );
+ break;
+ case DIR_A_TO_B:
+ /* A --> B */
+ str = g_strdup_printf("%s==%s%s%s%s%s && %s==%s%s%s%s%s",
+ ct_get_filter_name(&conv->src_address, conv->sat, conv->port_type, FN_SRC_ADDRESS),
+ ep_address_to_str(&conv->src_address),
+ sport?" && ":"",
+ sport?ct_get_filter_name(&conv->src_address, conv->sat, conv->port_type, FN_SRC_PORT):"",
+ sport?"==":"",
+ sport?sport:"",
+ ct_get_filter_name(&conv->dst_address, conv->sat, conv->port_type, FN_DST_ADDRESS),
+ ep_address_to_str(&conv->dst_address),
+ dport?" && ":"",
+ dport?ct_get_filter_name(&conv->dst_address, conv->sat, conv->port_type, FN_DST_PORT):"",
+ dport?"==":"",
+ dport?dport:""
+ );
+ break;
+ case DIR_A_FROM_B:
+ /* A <-- B */
+ str = g_strdup_printf("%s==%s%s%s%s%s && %s==%s%s%s%s%s",
+ ct_get_filter_name(&conv->src_address, conv->sat, conv->port_type, FN_DST_ADDRESS),
+ ep_address_to_str(&conv->src_address),
+ sport?" && ":"",
+ sport?ct_get_filter_name(&conv->src_address, conv->sat, conv->port_type, FN_DST_PORT):"",
+ sport?"==":"",
+ sport?sport:"",
+ ct_get_filter_name(&conv->dst_address, conv->sat, conv->port_type, FN_SRC_ADDRESS),
+ ep_address_to_str(&conv->dst_address),
+ dport?" && ":"",
+ dport?ct_get_filter_name(&conv->dst_address, conv->sat, conv->port_type, FN_SRC_PORT):"",
+ dport?"==":"",
+ dport?dport:""
+ );
+ break;
+ case DIR_A_TO_FROM_ANY:
+ /* A <-> ANY */
+ str = g_strdup_printf("%s==%s%s%s%s%s",
+ ct_get_filter_name(&conv->src_address, conv->sat, conv->port_type, FN_ANY_ADDRESS),
+ ep_address_to_str(&conv->src_address),
+ sport?" && ":"",
+ sport?ct_get_filter_name(&conv->src_address, conv->sat, conv->port_type, FN_ANY_PORT):"",
+ sport?"==":"",
+ sport?sport:""
+ );
+ break;
+ case DIR_A_TO_ANY:
+ /* A --> ANY */
+ str = g_strdup_printf("%s==%s%s%s%s%s",
+ ct_get_filter_name(&conv->src_address, conv->sat, conv->port_type, FN_SRC_ADDRESS),
+ ep_address_to_str(&conv->src_address),
+ sport?" && ":"",
+ sport?ct_get_filter_name(&conv->src_address, conv->sat, conv->port_type, FN_SRC_PORT):"",
+ sport?"==":"",
+ sport?sport:""
+ );
+ break;
+ case DIR_A_FROM_ANY:
+ /* A <-- ANY */
+ str = g_strdup_printf("%s==%s%s%s%s%s",
+ ct_get_filter_name(&conv->src_address, conv->sat, conv->port_type, FN_DST_ADDRESS),
+ ep_address_to_str(&conv->src_address),
+ sport?" && ":"",
+ sport?ct_get_filter_name(&conv->src_address, conv->sat, conv->port_type, FN_DST_PORT):"",
+ sport?"==":"",
+ sport?sport:""
+ );
+ break;
+ case DIR_ANY_TO_FROM_B:
+ /* ANY <-> B */
+ str = g_strdup_printf("%s==%s%s%s%s%s",
+ ct_get_filter_name(&conv->dst_address, conv->sat, conv->port_type, FN_ANY_ADDRESS),
+ ep_address_to_str(&conv->dst_address),
+ dport?" && ":"",
+ dport?ct_get_filter_name(&conv->dst_address, conv->sat, conv->port_type, FN_ANY_PORT):"",
+ dport?"==":"",
+ dport?dport:""
+ );
+ break;
+ case DIR_ANY_FROM_B:
+ /* ANY <-- B */
+ str = g_strdup_printf("%s==%s%s%s%s%s",
+ ct_get_filter_name(&conv->dst_address, conv->sat, conv->port_type, FN_SRC_ADDRESS),
+ ep_address_to_str(&conv->dst_address),
+ dport?" && ":"",
+ dport?ct_get_filter_name(&conv->dst_address, conv->sat, conv->port_type, FN_SRC_PORT):"",
+ dport?"==":"",
+ dport?dport:""
+ );
+ break;
+ case DIR_ANY_TO_B:
+ /* ANY --> B */
+ str = g_strdup_printf("%s==%s%s%s%s%s",
+ ct_get_filter_name(&conv->dst_address, conv->sat, conv->port_type, FN_DST_ADDRESS),
+ ep_address_to_str(&conv->dst_address),
+ dport?" && ":"",
+ dport?ct_get_filter_name(&conv->dst_address, conv->sat, conv->port_type, FN_DST_PORT):"",
+ dport?"==":"",
+ dport?dport:""
+ );
+ break;
+ default:
+ g_assert_not_reached();
+ }
+
+ apply_selected_filter (callback_action, str);
+
+ g_free (str);
+}
+
+static gboolean
+ct_show_popup_menu_cb(void *widg _U_, GdkEvent *event, conversations_table *ct)
+{
+ GdkEventButton *bevent = (GdkEventButton *)event;
+
+ if(event->type==GDK_BUTTON_PRESS && bevent->button==3){
+ gtk_menu_popup(GTK_MENU(ct->menu), NULL, NULL, NULL, NULL,
+ bevent->button, bevent->time);
+ }
+
+ return FALSE;
+}
+
+
+/* As Selected */
+static void
+conv_apply_as_selected_AtofromB_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_MATCH(ACTYPE_SELECTED, DIR_A_TO_FROM_B));
+}
+
+static void
+conv_apply_as_selected_AtoB_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_MATCH(ACTYPE_SELECTED, DIR_A_TO_B));
+}
+
+static void
+conv_apply_as_selected_AfromB_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_MATCH(ACTYPE_SELECTED, DIR_A_FROM_B));
+}
+
+static void
+conv_apply_as_selected_AtofromAny_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_MATCH(ACTYPE_SELECTED, DIR_A_TO_FROM_ANY));
+}
+
+static void
+conv_apply_as_selected_AtoAny_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_MATCH(ACTYPE_SELECTED, DIR_A_TO_ANY));
+}
+
+static void
+conv_apply_as_selected_AfromAny_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_MATCH(ACTYPE_SELECTED, DIR_A_FROM_ANY));
+}
+
+static void
+conv_apply_as_selected_AnytofromB_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_MATCH(ACTYPE_SELECTED, DIR_ANY_TO_FROM_B));
+}
+
+
+static void
+conv_apply_as_selected_AnyfromB_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_MATCH(ACTYPE_SELECTED, DIR_ANY_FROM_B));
+}
+
+static void
+conv_apply_as_selected_AnytoB_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_MATCH(ACTYPE_SELECTED, DIR_ANY_TO_B));
+}
+
+/* As Not Selected */
+static void
+conv_apply_as_not_selected_AtofromB_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_MATCH(ACTYPE_NOT_SELECTED, DIR_A_TO_FROM_B));
+}
+
+static void
+conv_apply_as_not_selected_AtoB_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_MATCH(ACTYPE_NOT_SELECTED, DIR_A_TO_B));
+}
+
+static void
+conv_apply_as_not_selected_AfromB_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_MATCH(ACTYPE_NOT_SELECTED, DIR_A_FROM_B));
+}
+
+static void
+conv_apply_as_not_selected_AtofromAny_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_MATCH(ACTYPE_NOT_SELECTED, DIR_A_TO_FROM_ANY));
+}
+
+static void
+conv_apply_as_not_selected_AtoAny_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_MATCH(ACTYPE_NOT_SELECTED, DIR_A_TO_ANY));
+}
+
+static void
+conv_apply_as_not_selected_AfromAny_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_MATCH(ACTYPE_NOT_SELECTED, DIR_A_FROM_ANY));
+}
+
+static void
+conv_apply_as_not_selected_AnytofromB_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_MATCH(ACTYPE_NOT_SELECTED, DIR_ANY_TO_FROM_B));
+}
+
+static void
+conv_apply_as_not_selected_AnyfromB_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_MATCH(ACTYPE_NOT_SELECTED, DIR_ANY_FROM_B));
+}
+
+static void
+conv_apply_as_not_selected_AnytoB_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_MATCH(ACTYPE_NOT_SELECTED, DIR_ANY_TO_B));
+}
+
+/* And Selected */
+static void
+conv_apply_and_selected_AtofromB_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_MATCH(ACTYPE_AND_SELECTED, DIR_A_TO_FROM_B));
+}
+
+static void
+conv_apply_and_selected_AtoB_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_MATCH(ACTYPE_AND_SELECTED, DIR_A_TO_B));
+}
+
+static void
+conv_apply_and_selected_AfromB_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_MATCH(ACTYPE_AND_SELECTED, DIR_A_FROM_B));
+}
+
+static void
+conv_apply_and_selected_AtofromAny_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_MATCH(ACTYPE_AND_SELECTED, DIR_A_TO_FROM_ANY));
+}
+
+static void
+conv_apply_and_selected_AtoAny_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_MATCH(ACTYPE_AND_SELECTED, DIR_A_TO_ANY));
+}
+
+static void
+conv_apply_and_selected_AfromAny_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_MATCH(ACTYPE_AND_SELECTED, DIR_A_FROM_ANY));
+}
+
+static void
+conv_apply_and_selected_AnytofromB_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_MATCH(ACTYPE_AND_SELECTED, DIR_ANY_TO_FROM_B));
+}
+
+static void
+conv_apply_and_selected_AnyfromB_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_MATCH(ACTYPE_AND_SELECTED, DIR_ANY_FROM_B));
+}
+
+static void
+conv_apply_and_selected_AnytoB_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_MATCH(ACTYPE_AND_SELECTED, DIR_ANY_TO_B));
+}
+
+/* Or Selected */
+static void
+conv_apply_or_selected_AtofromB_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_MATCH(ACTYPE_OR_SELECTED, DIR_A_TO_FROM_B));
+}
+
+static void
+conv_apply_or_selected_AtoB_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_MATCH(ACTYPE_OR_SELECTED, DIR_A_TO_B));
+}
+
+static void
+conv_apply_or_selected_AfromB_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_MATCH(ACTYPE_OR_SELECTED, DIR_A_FROM_B));
+}
+
+static void
+conv_apply_or_selected_AtofromAny_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_MATCH(ACTYPE_OR_SELECTED, DIR_A_TO_FROM_ANY));
+}
+
+static void
+conv_apply_or_selected_AtoAny_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_MATCH(ACTYPE_OR_SELECTED, DIR_A_TO_ANY));
+}
+
+static void
+conv_apply_or_selected_AfromAny_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_MATCH(ACTYPE_OR_SELECTED, DIR_A_FROM_ANY));
+}
+
+static void
+conv_apply_or_selected_AnytofromB_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_MATCH(ACTYPE_OR_SELECTED, DIR_ANY_TO_FROM_B));
+}
+
+static void
+conv_apply_or_selected_AnyfromB_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_MATCH(ACTYPE_OR_SELECTED, DIR_ANY_FROM_B));
+}
+
+static void
+conv_apply_or_selected_AnytoB_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_MATCH(ACTYPE_OR_SELECTED, DIR_ANY_TO_B));
+}
+
+/* And Not Selected */
+static void
+conv_apply_and_not_selected_AtofromB_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_MATCH(ACTYPE_AND_NOT_SELECTED, DIR_A_TO_FROM_B));
+}
+
+static void
+conv_apply_and_not_selected_AtoB_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_MATCH(ACTYPE_AND_NOT_SELECTED, DIR_A_TO_B));
+}
+
+static void
+conv_apply_and_not_selected_AfromB_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_MATCH(ACTYPE_AND_NOT_SELECTED, DIR_A_FROM_B));
+}
+
+static void
+conv_apply_and_not_selected_AtofromAny_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_MATCH(ACTYPE_AND_NOT_SELECTED, DIR_A_TO_FROM_ANY));
+}
+
+static void
+conv_apply_and_not_selected_AtoAny_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_MATCH(ACTYPE_AND_NOT_SELECTED, DIR_A_TO_ANY));
+}
+
+static void
+conv_apply_and_not_selected_AfromAny_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_MATCH(ACTYPE_AND_NOT_SELECTED, DIR_A_FROM_ANY));
+}
+
+static void
+conv_apply_and_not_selected_AnytofromB_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_MATCH(ACTYPE_AND_NOT_SELECTED, DIR_ANY_TO_FROM_B));
+}
+
+static void
+conv_apply_and_not_selected_AnyfromB_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_MATCH(ACTYPE_AND_NOT_SELECTED, DIR_ANY_FROM_B));
+}
+
+static void
+conv_apply_and_not_selected_AnytoB_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_MATCH(ACTYPE_AND_NOT_SELECTED, DIR_ANY_TO_B));
+}
+
+/* Or Not Selected */
+static void
+conv_apply_or_not_selected_AtofromB_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_MATCH(ACTYPE_OR_NOT_SELECTED, DIR_A_TO_FROM_B));
+}
+
+static void
+conv_apply_or_not_selected_AtoB_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_MATCH(ACTYPE_AND_NOT_SELECTED, DIR_A_TO_B));
+}
+
+static void
+conv_apply_or_not_selected_AfromB_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_MATCH(ACTYPE_OR_NOT_SELECTED, DIR_A_FROM_B));
+}
+
+static void
+conv_apply_or_not_selected_AtofromAny_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_MATCH(ACTYPE_OR_NOT_SELECTED, DIR_A_TO_FROM_ANY));
+}
+
+static void
+conv_apply_or_not_selected_AtoAny_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_MATCH(ACTYPE_OR_NOT_SELECTED, DIR_A_TO_ANY));
+}
+
+static void
+conv_apply_or_not_selected_AfromAny_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_MATCH(ACTYPE_OR_NOT_SELECTED, DIR_A_FROM_ANY));
+}
+
+static void
+conv_apply_or_not_selected_AnytofromB_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_MATCH(ACTYPE_OR_NOT_SELECTED, DIR_ANY_TO_FROM_B));
+}
+
+static void
+conv_apply_or_not_selected_AnyfromB_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_MATCH(ACTYPE_OR_NOT_SELECTED, DIR_ANY_FROM_B));
+}
+
+static void
+conv_apply_or_not_selected_AnytoB_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_MATCH(ACTYPE_OR_NOT_SELECTED, DIR_ANY_TO_B));
+}
+
+
+/* Prepare As Selected*/
+static void
+conv_prepare_as_selected_AtofromB_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_PREPARE(ACTYPE_SELECTED, DIR_A_TO_FROM_B));
+}
+
+static void
+conv_prepare_as_selected_AtoB_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_PREPARE(ACTYPE_SELECTED, DIR_A_TO_B));
+}
+
+static void
+conv_prepare_as_selected_AfromB_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_PREPARE(ACTYPE_SELECTED, DIR_A_FROM_B));
+}
+
+static void
+conv_prepare_as_selected_AtofromAny_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_PREPARE(ACTYPE_SELECTED, DIR_A_TO_FROM_ANY));
+}
+
+static void
+conv_prepare_as_selected_AtoAny_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_PREPARE(ACTYPE_SELECTED, DIR_A_TO_ANY));
+}
+
+static void
+conv_prepare_as_selected_AfromAny_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_PREPARE(ACTYPE_SELECTED, DIR_A_FROM_ANY));
+}
+
+static void
+conv_prepare_as_selected_AnytofromB_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_PREPARE(ACTYPE_SELECTED, DIR_ANY_TO_FROM_B));
+}
+
+static void
+conv_prepare_as_selected_AnyfromB_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_PREPARE(ACTYPE_SELECTED, DIR_ANY_FROM_B));
+}
+
+static void
+conv_prepare_as_selected_AnytoB_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_PREPARE(ACTYPE_SELECTED, DIR_ANY_TO_B));
+}
+
+/* Prepare As Not Selected */
+static void
+conv_prepare_as_not_selected_AtofromB_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_PREPARE(ACTYPE_NOT_SELECTED, DIR_A_TO_FROM_B));
+}
+
+static void
+conv_prepare_as_not_selected_AtoB_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_PREPARE(ACTYPE_NOT_SELECTED, DIR_A_TO_B));
+}
+
+static void
+conv_prepare_as_not_selected_AfromB_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_PREPARE(ACTYPE_NOT_SELECTED, DIR_A_FROM_B));
+}
+
+static void
+conv_prepare_as_not_selected_AtofromAny_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_PREPARE(ACTYPE_NOT_SELECTED, DIR_A_TO_FROM_ANY));
+}
+
+static void
+conv_prepare_as_not_selected_AtoAny_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_PREPARE(ACTYPE_NOT_SELECTED, DIR_A_TO_ANY));
+}
+
+static void
+conv_prepare_as_not_selected_AfromAny_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_PREPARE(ACTYPE_NOT_SELECTED, DIR_A_FROM_ANY));
+}
+
+static void
+conv_prepare_as_not_selected_AnytofromB_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_PREPARE(ACTYPE_NOT_SELECTED, DIR_ANY_TO_FROM_B));
+}
+
+static void
+conv_prepare_as_not_selected_AnyfromB_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_PREPARE(ACTYPE_NOT_SELECTED, DIR_ANY_FROM_B));
+}
+
+static void
+conv_prepare_as_not_selected_AnytoB_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_PREPARE(ACTYPE_NOT_SELECTED, DIR_ANY_TO_B));
+}
+
+/* Prepare And Selected */
+static void
+conv_prepare_and_selected_AtofromB_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_PREPARE(ACTYPE_AND_SELECTED, DIR_A_TO_FROM_B));
+}
+
+static void
+conv_prepare_and_selected_AtoB_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_PREPARE(ACTYPE_AND_SELECTED, DIR_A_TO_B));
+}
+
+static void
+conv_prepare_and_selected_AfromB_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_PREPARE(ACTYPE_AND_SELECTED, DIR_A_FROM_B));
+}
+
+static void
+conv_prepare_and_selected_AtofromAny_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_PREPARE(ACTYPE_AND_SELECTED, DIR_A_TO_FROM_ANY));
+}
+
+static void
+conv_prepare_and_selected_AtoAny_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_PREPARE(ACTYPE_AND_SELECTED, DIR_A_TO_ANY));
+}
+
+static void
+conv_prepare_and_selected_AfromAny_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_PREPARE(ACTYPE_AND_SELECTED, DIR_A_FROM_ANY));
+}
+
+static void
+conv_prepare_and_selected_AnytofromB_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_PREPARE(ACTYPE_AND_SELECTED, DIR_ANY_TO_FROM_B));
+}
+
+static void
+conv_prepare_and_selected_AnyfromB_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_PREPARE(ACTYPE_AND_SELECTED, DIR_ANY_FROM_B));
+}
+
+static void
+conv_prepare_and_selected_AnytoB_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_PREPARE(ACTYPE_AND_SELECTED, DIR_ANY_TO_B));
+}
+
+/* Prepare Or Selected */
+static void
+conv_prepare_or_selected_AtofromB_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_PREPARE(ACTYPE_OR_SELECTED, DIR_A_TO_FROM_B));
+}
+
+static void
+conv_prepare_or_selected_AtoB_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_PREPARE(ACTYPE_OR_SELECTED, DIR_A_TO_B));
+}
+
+static void
+conv_prepare_or_selected_AfromB_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_PREPARE(ACTYPE_OR_SELECTED, DIR_A_FROM_B));
+}
+
+static void
+conv_prepare_or_selected_AtofromAny_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_PREPARE(ACTYPE_OR_SELECTED, DIR_A_TO_FROM_ANY));
+}
+
+static void
+conv_prepare_or_selected_AtoAny_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_PREPARE(ACTYPE_OR_SELECTED, DIR_A_TO_ANY));
+}
+
+static void
+conv_prepare_or_selected_AfromAny_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_PREPARE(ACTYPE_OR_SELECTED, DIR_A_FROM_ANY));
+}
+
+static void
+conv_prepare_or_selected_AnytofromB_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_PREPARE(ACTYPE_OR_SELECTED, DIR_ANY_TO_FROM_B));
+}
+
+static void
+conv_prepare_or_selected_AnyfromB_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_PREPARE(ACTYPE_OR_SELECTED, DIR_ANY_FROM_B));
+}
+
+static void
+conv_prepare_or_selected_AnytoB_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_PREPARE(ACTYPE_OR_SELECTED, DIR_ANY_TO_B));
+}
+
+/* Prepare And Not Selected */
+static void
+conv_prepare_and_not_selected_AtofromB_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_PREPARE(ACTYPE_AND_NOT_SELECTED, DIR_A_TO_FROM_B));
+}
+
+static void
+conv_prepare_and_not_selected_AtoB_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_PREPARE(ACTYPE_AND_NOT_SELECTED, DIR_A_TO_B));
+}
+
+static void
+conv_prepare_and_not_selected_AfromB_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_PREPARE(ACTYPE_AND_NOT_SELECTED, DIR_A_FROM_B));
+}
+
+static void
+conv_prepare_and_not_selected_AtofromAny_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_PREPARE(ACTYPE_AND_NOT_SELECTED, DIR_A_TO_FROM_ANY));
+}
+
+static void
+conv_prepare_and_not_selected_AtoAny_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_PREPARE(ACTYPE_AND_NOT_SELECTED, DIR_A_TO_ANY));
+}
+
+static void
+conv_prepare_and_not_selected_AfromAny_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_PREPARE(ACTYPE_AND_NOT_SELECTED, DIR_A_FROM_ANY));
+}
+
+static void
+conv_prepare_and_not_selected_AnytofromB_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_PREPARE(ACTYPE_AND_NOT_SELECTED, DIR_ANY_TO_FROM_B));
+}
+
+static void
+conv_prepare_and_not_selected_AnyfromB_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_PREPARE(ACTYPE_AND_NOT_SELECTED, DIR_ANY_FROM_B));
+}
+
+static void
+conv_prepare_and_not_selected_AnytoB_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_PREPARE(ACTYPE_AND_NOT_SELECTED, DIR_ANY_TO_B));
+}
+
+/* Prepare Or Not Selected */
+static void
+conv_prepare_or_not_selected_AtofromB_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_PREPARE(ACTYPE_OR_NOT_SELECTED, DIR_A_TO_FROM_B));
+}
+
+static void
+conv_prepare_or_not_selected_AtoB_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_PREPARE(ACTYPE_AND_NOT_SELECTED, DIR_A_TO_B));
+}
+
+static void
+conv_prepare_or_not_selected_AfromB_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_PREPARE(ACTYPE_OR_NOT_SELECTED, DIR_A_FROM_B));
+}
+
+static void
+conv_prepare_or_not_selected_AtofromAny_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_PREPARE(ACTYPE_OR_NOT_SELECTED, DIR_A_TO_FROM_ANY));
+}
+
+static void
+conv_prepare_or_not_selected_AtoAny_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_PREPARE(ACTYPE_OR_NOT_SELECTED, DIR_A_TO_ANY));
+}
+
+static void
+conv_prepare_or_not_selected_AfromAny_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_PREPARE(ACTYPE_OR_NOT_SELECTED, DIR_A_FROM_ANY));
+}
+
+static void
+conv_prepare_or_not_selected_AnytofromB_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_PREPARE(ACTYPE_OR_NOT_SELECTED, DIR_ANY_TO_FROM_B));
+}
+
+static void
+conv_prepare_or_not_selected_AnyfromB_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_PREPARE(ACTYPE_OR_NOT_SELECTED, DIR_ANY_FROM_B));
+}
+
+static void
+conv_prepare_or_not_selected_AnytoB_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_PREPARE(ACTYPE_OR_NOT_SELECTED, DIR_ANY_TO_B));
+}
+
+/* Find packet */
+static void
+conv_find_AtofromB_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_FIND_FRAME(ACTYPE_SELECTED, DIR_A_TO_FROM_B));
+}
+
+static void
+conv_find_AtoB_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_FIND_FRAME(ACTYPE_SELECTED, DIR_A_TO_B));
+}
+
+static void
+conv_find_AfromB_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_FIND_FRAME(ACTYPE_SELECTED, DIR_A_FROM_B));
+}
+
+static void
+conv_find_AtofromAny_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_FIND_FRAME(ACTYPE_SELECTED, DIR_A_TO_FROM_ANY));
+}
+
+static void
+conv_find_AtoAny_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_FIND_FRAME(ACTYPE_SELECTED, DIR_A_TO_ANY));
+}
+
+static void
+conv_find_AfromAny_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_FIND_FRAME(ACTYPE_SELECTED, DIR_A_FROM_ANY));
+}
+
+static void
+conv_find_AnytofromB_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_FIND_FRAME(ACTYPE_SELECTED, DIR_ANY_TO_FROM_B));
+}
+
+static void
+conv_find_AnyfromB_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_FIND_FRAME(ACTYPE_SELECTED, DIR_ANY_FROM_B));
+}
+
+static void
+conv_find_AnytoB_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_FIND_FRAME(ACTYPE_SELECTED, DIR_ANY_TO_B));
+}
+
+/* Find next */
+static void
+conv_find_next_AtofromB_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_FIND_NEXT(ACTYPE_NOT_SELECTED, DIR_A_TO_FROM_B));
+}
+
+static void
+conv_find_next_AtoB_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_FIND_NEXT(ACTYPE_NOT_SELECTED, DIR_A_TO_B));
+}
+
+static void
+conv_find_next_AfromB_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_FIND_NEXT(ACTYPE_NOT_SELECTED, DIR_A_FROM_B));
+}
+
+static void
+conv_find_next_AtofromAny_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_FIND_NEXT(ACTYPE_NOT_SELECTED, DIR_A_TO_FROM_ANY));
+}
+
+static void
+conv_find_next_AtoAny_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_FIND_NEXT(ACTYPE_NOT_SELECTED, DIR_A_TO_ANY));
+}
+
+static void
+conv_find_next_AfromAny_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_FIND_NEXT(ACTYPE_NOT_SELECTED, DIR_A_FROM_ANY));
+}
+
+static void
+conv_find_next_AnytofromB_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_FIND_NEXT(ACTYPE_NOT_SELECTED, DIR_ANY_TO_FROM_B));
+}
+
+static void
+conv_find_next_AnyfromB_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_FIND_NEXT(ACTYPE_NOT_SELECTED, DIR_ANY_FROM_B));
+}
+
+static void
+conv_find_next_AnytoB_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_FIND_NEXT(ACTYPE_NOT_SELECTED, DIR_ANY_TO_B));
+}
+
+/* Find Previous */
+static void
+conv_find_previous_AtofromB_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_FIND_PREVIOUS(ACTYPE_AND_SELECTED, DIR_A_TO_FROM_B));
+}
+
+static void
+conv_find_previous_AtoB_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_FIND_PREVIOUS(ACTYPE_AND_SELECTED, DIR_A_TO_B));
+}
+
+static void
+conv_find_previous_AfromB_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_FIND_PREVIOUS(ACTYPE_AND_SELECTED, DIR_A_FROM_B));
+}
+
+static void
+conv_find_previous_AtofromAny_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_FIND_PREVIOUS(ACTYPE_AND_SELECTED, DIR_A_TO_FROM_ANY));
+}
+
+static void
+conv_find_previous_AtoAny_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_FIND_PREVIOUS(ACTYPE_AND_SELECTED, DIR_A_TO_ANY));
+}
+
+static void
+conv_find_previous_AfromAny_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_FIND_PREVIOUS(ACTYPE_AND_SELECTED, DIR_A_FROM_ANY));
+}
+
+static void
+conv_find_previous_AnytofromB_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_FIND_PREVIOUS(ACTYPE_AND_SELECTED, DIR_ANY_TO_FROM_B));
+}
+
+static void
+conv_find_previous_AnyfromB_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_FIND_PREVIOUS(ACTYPE_AND_SELECTED, DIR_ANY_FROM_B));
+}
+
+static void
+conv_find_previous_AnytoB_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_FIND_PREVIOUS(ACTYPE_AND_SELECTED, DIR_ANY_TO_B));
+}
+
+/* Colorize Conversation */
+
+static void
+conv_color_AtofromB_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_COLORIZE(ACTYPE_SELECTED, DIR_A_TO_FROM_B));
+}
+
+static void
+conv_color_AtoB_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_COLORIZE(ACTYPE_SELECTED, DIR_A_TO_B));
+}
+
+static void
+conv_color_AfromB_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_COLORIZE(ACTYPE_SELECTED, DIR_A_FROM_B));
+}
+
+static void
+conv_color_AtofromAny_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_COLORIZE(ACTYPE_SELECTED, DIR_A_TO_FROM_ANY));
+}
+
+static void
+conv_color_AtoAny_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_COLORIZE(ACTYPE_SELECTED, DIR_A_TO_ANY));
+}
+
+static void
+conv_color_AfromAny_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_COLORIZE(ACTYPE_SELECTED, DIR_A_FROM_ANY));
+}
+
+static void
+conv_color_AnytofromB_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_COLORIZE(ACTYPE_SELECTED, DIR_ANY_TO_FROM_B));
+}
+
+static void
+conv_color_AnyfromB_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_COLORIZE(ACTYPE_SELECTED, DIR_ANY_FROM_B));
+}
+
+static void
+conv_color_AnytoB_cb(GtkAction *action _U_, gpointer user_data)
+{
+ ct_select_filter_cb( NULL, user_data, CALLBACK_COLORIZE(ACTYPE_SELECTED, DIR_ANY_TO_B));
+}
+static const char *ui_desc_conv_filter_popup =
+"<ui>\n"
+" <popup name='ConversationFilterPopup' action='PopupAction'>\n"
+" <menu name= 'ApplyAsFilter' action='/Apply as Filter'>\n"
+" <menu name= 'ApplyAsFilterSelected' action='/Apply as Filter/Selected'>\n"
+" <menuitem action='/Apply as Filter/Selected/A_to_from_B'/>\n"
+" <menuitem action='/Apply as Filter/Selected/A_to_B'/>\n"
+" <menuitem action='/Apply as Filter/Selected/A_from_B'/>\n"
+" <menuitem action='/Apply as Filter/Selected/A_to_from_Any'/>\n"
+" <menuitem action='/Apply as Filter/Selected/A_to_Any'/>\n"
+" <menuitem action='/Apply as Filter/Selected/A_from_Any'/>\n"
+" <menuitem action='/Apply as Filter/Selected/Any_tofrom_B'/>\n"
+" <menuitem action='/Apply as Filter/Selected/Any_from_B'/>\n"
+" <menuitem action='/Apply as Filter/Selected/Any_to_B'/>\n"
+" </menu>\n"
+" <menu name= 'ApplyAsFilterNotSelected' action='/Apply as Filter/Not Selected'>\n"
+" <menuitem action='/Apply as Filter/Not Selected/A_to_from_B'/>\n"
+" <menuitem action='/Apply as Filter/Not Selected/A_to_B'/>\n"
+" <menuitem action='/Apply as Filter/Not Selected/A_from_B'/>\n"
+" <menuitem action='/Apply as Filter/Not Selected/A_to_from_Any'/>\n"
+" <menuitem action='/Apply as Filter/Not Selected/A_to_Any'/>\n"
+" <menuitem action='/Apply as Filter/Not Selected/A_from_Any'/>\n"
+" <menuitem action='/Apply as Filter/Not Selected/Any_tofrom_B'/>\n"
+" <menuitem action='/Apply as Filter/Not Selected/Any_from_B'/>\n"
+" <menuitem action='/Apply as Filter/Not Selected/Any_to_B'/>\n"
+" </menu>\n"
+" <menu name= 'ApplyAsFilterAndSelected' action='/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " and Selected'>\n"
+" <menuitem action='/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " and Selected/A_to_from_B'/>\n"
+" <menuitem action='/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " and Selected/A_to_B'/>\n"
+" <menuitem action='/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " and Selected/A_from_B'/>\n"
+" <menuitem action='/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " and Selected/A_to_from_Any'/>\n"
+" <menuitem action='/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " and Selected/A_to_Any'/>\n"
+" <menuitem action='/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " and Selected/A_from_Any'/>\n"
+" <menuitem action='/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " and Selected/Any_tofrom_B'/>\n"
+" <menuitem action='/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " and Selected/Any_from_B'/>\n"
+" <menuitem action='/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " and Selected/Any_to_B'/>\n"
+" </menu>\n"
+" <menu name= 'ApplyAsFilterOrSelected' action='/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " or Selected'>\n"
+" <menuitem action='/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " or Selected/A_to_from_B'/>\n"
+" <menuitem action='/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " or Selected/A_to_B'/>\n"
+" <menuitem action='/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " or Selected/A_from_B'/>\n"
+" <menuitem action='/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " or Selected/A_to_from_Any'/>\n"
+" <menuitem action='/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " or Selected/A_to_Any'/>\n"
+" <menuitem action='/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " or Selected/A_from_Any'/>\n"
+" <menuitem action='/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " or Selected/Any_tofrom_B'/>\n"
+" <menuitem action='/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " or Selected/Any_from_B'/>\n"
+" <menuitem action='/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " or Selected/Any_to_B'/>\n"
+" </menu>\n"
+" <menu name= 'ApplyAsFilterAndNotSelected' action='/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " and not Selected'>\n"
+" <menuitem action='/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " and not Selected/A_to_from_B'/>\n"
+" <menuitem action='/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " and not Selected/A_to_B'/>\n"
+" <menuitem action='/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " and not Selected/A_from_B'/>\n"
+" <menuitem action='/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " and not Selected/A_to_from_Any'/>\n"
+" <menuitem action='/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " and not Selected/A_to_Any'/>\n"
+" <menuitem action='/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " and not Selected/A_from_Any'/>\n"
+" <menuitem action='/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " and not Selected/Any_tofrom_B'/>\n"
+" <menuitem action='/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " and not Selected/Any_from_B'/>\n"
+" <menuitem action='/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " and not Selected/Any_to_B'/>\n"
+" </menu>\n"
+" <menu name= 'ApplyAsFilterOrNotSelected' action='/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " or not Selected'>\n"
+" <menuitem action='/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " or not Selected/A_to_from_B'/>\n"
+" <menuitem action='/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " or not Selected/A_to_B'/>\n"
+" <menuitem action='/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " or not Selected/A_from_B'/>\n"
+" <menuitem action='/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " or not Selected/A_to_from_Any'/>\n"
+" <menuitem action='/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " or not Selected/A_to_Any'/>\n"
+" <menuitem action='/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " or not Selected/A_from_Any'/>\n"
+" <menuitem action='/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " or not Selected/Any_tofrom_B'/>\n"
+" <menuitem action='/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " or not Selected/Any_from_B'/>\n"
+" <menuitem action='/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " or not Selected/Any_to_B'/>\n"
+" </menu>\n"
+" </menu>\n"
+" <menu name= 'PrepareAFilter' action='/Prepare a Filter'>\n"
+" <menu name= 'PrepareAFilterSelected' action='/Prepare a Filter/Selected'>\n"
+" <menuitem action='/Prepare a Filter/Selected/A_to_from_B'/>\n"
+" <menuitem action='/Prepare a Filter/Selected/A_to_B'/>\n"
+" <menuitem action='/Prepare a Filter/Selected/A_from_B'/>\n"
+" <menuitem action='/Prepare a Filter/Selected/A_to_from_Any'/>\n"
+" <menuitem action='/Prepare a Filter/Selected/A_to_Any'/>\n"
+" <menuitem action='/Prepare a Filter/Selected/A_from_Any'/>\n"
+" <menuitem action='/Prepare a Filter/Selected/Any_tofrom_B'/>\n"
+" <menuitem action='/Prepare a Filter/Selected/Any_from_B'/>\n"
+" <menuitem action='/Prepare a Filter/Selected/Any_to_B'/>\n"
+" </menu>\n"
+" <menu name= 'PrepareAFilterNotSelected' action='/Prepare a Filter/Not Selected'>\n"
+" <menuitem action='/Prepare a Filter/Not Selected/A_to_from_B'/>\n"
+" <menuitem action='/Prepare a Filter/Not Selected/A_to_B'/>\n"
+" <menuitem action='/Prepare a Filter/Not Selected/A_from_B'/>\n"
+" <menuitem action='/Prepare a Filter/Not Selected/A_to_from_Any'/>\n"
+" <menuitem action='/Prepare a Filter/Not Selected/A_to_Any'/>\n"
+" <menuitem action='/Prepare a Filter/Not Selected/A_from_Any'/>\n"
+" <menuitem action='/Prepare a Filter/Not Selected/Any_tofrom_B'/>\n"
+" <menuitem action='/Prepare a Filter/Not Selected/Any_from_B'/>\n"
+" <menuitem action='/Prepare a Filter/Not Selected/Any_to_B'/>\n"
+" </menu>\n"
+" <menu name= 'PrepareAFilterAndSelected' action='/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " and Selected'>\n"
+" <menuitem action='/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " and Selected/A_to_from_B'/>\n"
+" <menuitem action='/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " and Selected/A_to_B'/>\n"
+" <menuitem action='/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " and Selected/A_from_B'/>\n"
+" <menuitem action='/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " and Selected/A_to_from_Any'/>\n"
+" <menuitem action='/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " and Selected/A_to_Any'/>\n"
+" <menuitem action='/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " and Selected/A_from_Any'/>\n"
+" <menuitem action='/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " and Selected/Any_tofrom_B'/>\n"
+" <menuitem action='/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " and Selected/Any_from_B'/>\n"
+" <menuitem action='/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " and Selected/Any_to_B'/>\n"
+" </menu>\n"
+" <menu name= 'PrepareAFilterOrSelected' action='/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " or Selected'>\n"
+" <menuitem action='/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " or Selected/A_to_from_B'/>\n"
+" <menuitem action='/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " or Selected/A_to_B'/>\n"
+" <menuitem action='/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " or Selected/A_from_B'/>\n"
+" <menuitem action='/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " or Selected/A_to_from_Any'/>\n"
+" <menuitem action='/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " or Selected/A_to_Any'/>\n"
+" <menuitem action='/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " or Selected/A_from_Any'/>\n"
+" <menuitem action='/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " or Selected/Any_tofrom_B'/>\n"
+" <menuitem action='/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " or Selected/Any_from_B'/>\n"
+" <menuitem action='/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " or Selected/Any_to_B'/>\n"
+" </menu>\n"
+" <menu name= 'PrepareAFilterAndNotSelected' action='/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " and not Selected'>\n"
+" <menuitem action='/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " and not Selected/A_to_from_B'/>\n"
+" <menuitem action='/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " and not Selected/A_to_B'/>\n"
+" <menuitem action='/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " and not Selected/A_from_B'/>\n"
+" <menuitem action='/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " and not Selected/A_to_from_Any'/>\n"
+" <menuitem action='/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " and not Selected/A_to_Any'/>\n"
+" <menuitem action='/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " and not Selected/A_from_Any'/>\n"
+" <menuitem action='/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " and not Selected/Any_tofrom_B'/>\n"
+" <menuitem action='/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " and not Selected/Any_from_B'/>\n"
+" <menuitem action='/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " and not Selected/Any_to_B'/>\n"
+" </menu>\n"
+" <menu name= 'PrepareAFilterOrNotSelected' action='/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " or not Selected'>\n"
+" <menuitem action='/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " or not Selected/A_to_from_B'/>\n"
+" <menuitem action='/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " or not Selected/A_to_B'/>\n"
+" <menuitem action='/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " or not Selected/A_from_B'/>\n"
+" <menuitem action='/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " or not Selected/A_to_from_Any'/>\n"
+" <menuitem action='/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " or not Selected/A_to_Any'/>\n"
+" <menuitem action='/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " or not Selected/A_from_Any'/>\n"
+" <menuitem action='/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " or not Selected/Any_tofrom_B'/>\n"
+" <menuitem action='/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " or not Selected/Any_from_B'/>\n"
+" <menuitem action='/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " or not Selected/Any_to_B'/>\n"
+" </menu>\n"
+" </menu>\n"
+" <menu name= 'FindPacket' action='/Find Packet'>\n"
+" <menu name= 'FindPacketFindPacket' action='/Find Packet/Find Packet'>\n"
+" <menuitem action='/Find Packet/Find Packet/A_to_from_B'/>\n"
+" <menuitem action='/Find Packet/Find Packet/A_to_B'/>\n"
+" <menuitem action='/Find Packet/Find Packet/A_from_B'/>\n"
+" <menuitem action='/Find Packet/Find Packet/A_to_from_Any'/>\n"
+" <menuitem action='/Find Packet/Find Packet/A_to_Any'/>\n"
+" <menuitem action='/Find Packet/Find Packet/A_from_Any'/>\n"
+" <menuitem action='/Find Packet/Find Packet/Any_tofrom_B'/>\n"
+" <menuitem action='/Find Packet/Find Packet/Any_from_B'/>\n"
+" <menuitem action='/Find Packet/Find Packet/Any_to_B'/>\n"
+" </menu>\n"
+" <menu name= 'FindPacketFindNext' action='/Find Packet/Find Next'>\n"
+" <menuitem action='/Find Packet/Find Next/A_to_from_B'/>\n"
+" <menuitem action='/Find Packet/Find Next/A_to_B'/>\n"
+" <menuitem action='/Find Packet/Find Next/A_from_B'/>\n"
+" <menuitem action='/Find Packet/Find Next/A_to_from_Any'/>\n"
+" <menuitem action='/Find Packet/Find Next/A_to_Any'/>\n"
+" <menuitem action='/Find Packet/Find Next/A_from_Any'/>\n"
+" <menuitem action='/Find Packet/Find Next/Any_tofrom_B'/>\n"
+" <menuitem action='/Find Packet/Find Next/Any_from_B'/>\n"
+" <menuitem action='/Find Packet/Find Next/Any_to_B'/>\n"
+" </menu>\n"
+" <menu name= 'FindPacketFindPrevious' action='/Find Packet/Find Previous'>\n"
+" <menuitem action='/Find Packet/Find Previous/A_to_from_B'/>\n"
+" <menuitem action='/Find Packet/Find Previous/A_to_B'/>\n"
+" <menuitem action='/Find Packet/Find Previous/A_from_B'/>\n"
+" <menuitem action='/Find Packet/Find Previous/A_to_from_Any'/>\n"
+" <menuitem action='/Find Packet/Find Previous/A_to_Any'/>\n"
+" <menuitem action='/Find Packet/Find Previous/A_from_Any'/>\n"
+" <menuitem action='/Find Packet/Find Previous/Any_tofrom_B'/>\n"
+" <menuitem action='/Find Packet/Find Previous/Any_from_B'/>\n"
+" <menuitem action='/Find Packet/Find Previous/Any_to_B'/>\n"
+" </menu>\n"
+" </menu>\n"
+" <menu name= 'ColorizeConversation' action='/Colorize Conversation'>\n"
+" <menuitem action='/Colorize Conversation/A_to_from_B'/>\n"
+" <menuitem action='/Colorize Conversation/A_to_B'/>\n"
+" <menuitem action='/Colorize Conversation/A_from_B'/>\n"
+" <menuitem action='/Colorize Conversation/A_to_from_Any'/>\n"
+" <menuitem action='/Colorize Conversation/A_to_Any'/>\n"
+" <menuitem action='/Colorize Conversation/A_from_Any'/>\n"
+" <menuitem action='/Colorize Conversation/Any_tofrom_B'/>\n"
+" <menuitem action='/Colorize Conversation/Any_from_B'/>\n"
+" <menuitem action='/Colorize Conversation/Any_to_B'/>\n"
+" </menu>\n"
+" </popup>\n"
+"</ui>\n";
+
+/*
+ * GtkActionEntry
+ * typedef struct {
+ * const gchar *name;
+ * const gchar *stock_id;
+ * const gchar *label;
+ * const gchar *accelerator;
+ * const gchar *tooltip;
+ * GCallback callback;
+ * } GtkActionEntry;
+ * const gchar *name; The name of the action.
+ * const gchar *stock_id; The stock id for the action, or the name of an icon from the icon theme.
+ * const gchar *label; The label for the action. This field should typically be marked for translation,
+ * see gtk_action_group_set_translation_domain().
+ * If label is NULL, the label of the stock item with id stock_id is used.
+ * const gchar *accelerator; The accelerator for the action, in the format understood by gtk_accelerator_parse().
+ * const gchar *tooltip; The tooltip for the action. This field should typically be marked for translation,
+ * see gtk_action_group_set_translation_domain().
+ * GCallback callback; The function to call when the action is activated.
+ *
+ */
+static const GtkActionEntry conv_filter_menu_entries[] = {
+ /* Top level */
+ { "/Apply as Filter", NULL, "Apply as Filter", NULL, NULL, NULL },
+ { "/Prepare a Filter", NULL, "Prepare a Filter", NULL, NULL, NULL },
+ { "/Find Packet", NULL, "Find Packet", NULL, NULL, NULL },
+ { "/Colorize Conversation", NULL, "Colorize Conversation", NULL, NULL, NULL },
+
+ /* Apply as */
+ { "/Apply as Filter/Selected", NULL, "Selected" , NULL, NULL, NULL },
+ { "/Apply as Filter/Not Selected", NULL, "Not Selected", NULL, NULL, NULL },
+ { "/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " and Selected", NULL, UTF8_HORIZONTAL_ELLIPSIS " and Selected", NULL, NULL, NULL },
+ { "/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " or Selected", NULL, UTF8_HORIZONTAL_ELLIPSIS " or Selected", NULL, NULL, NULL },
+ { "/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " and not Selected", NULL, UTF8_HORIZONTAL_ELLIPSIS " and not Selected", NULL, NULL, NULL },
+ { "/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " or not Selected", NULL, UTF8_HORIZONTAL_ELLIPSIS " or not Selected", NULL, NULL, NULL },
+
+ /* Apply as Selected */
+ { "/Apply as Filter/Selected/A_to_from_B", NULL, "A " UTF8_LEFT_RIGHT_ARROW " B", NULL, "A " UTF8_LEFT_RIGHT_ARROW " B", G_CALLBACK(conv_apply_as_selected_AtofromB_cb)},
+ { "/Apply as Filter/Selected/A_to_B", NULL, "A " UTF8_RIGHTWARDS_ARROW " B", NULL, "A " UTF8_RIGHTWARDS_ARROW " B", G_CALLBACK(conv_apply_as_selected_AtoB_cb)},
+ { "/Apply as Filter/Selected/A_from_B", NULL, "A " UTF8_LEFTWARDS_ARROW " B", NULL, "A " UTF8_LEFTWARDS_ARROW " B", G_CALLBACK(conv_apply_as_selected_AfromB_cb)},
+ { "/Apply as Filter/Selected/A_to_from_Any", NULL, "A " UTF8_LEFT_RIGHT_ARROW " Any",NULL, "A " UTF8_LEFT_RIGHT_ARROW " Any", G_CALLBACK(conv_apply_as_selected_AtofromAny_cb)},
+ { "/Apply as Filter/Selected/A_to_Any", NULL, "A " UTF8_RIGHTWARDS_ARROW " Any",NULL, "A " UTF8_LEFTWARDS_ARROW " Any", G_CALLBACK(conv_apply_as_selected_AtoAny_cb)},
+ { "/Apply as Filter/Selected/A_from_Any", NULL, "A " UTF8_LEFTWARDS_ARROW " Any",NULL, "A " UTF8_LEFTWARDS_ARROW " Any", G_CALLBACK(conv_apply_as_selected_AfromAny_cb)},
+ { "/Apply as Filter/Selected/Any_tofrom_B", NULL, "Any " UTF8_LEFT_RIGHT_ARROW " B",NULL, "Any " UTF8_LEFT_RIGHT_ARROW " B", G_CALLBACK(conv_apply_as_selected_AnytofromB_cb)},
+ { "/Apply as Filter/Selected/Any_to_B", NULL, "Any " UTF8_RIGHTWARDS_ARROW " B",NULL, "Any " UTF8_RIGHTWARDS_ARROW " B", G_CALLBACK(conv_apply_as_selected_AnytoB_cb)},
+ { "/Apply as Filter/Selected/Any_from_B", NULL, "Any " UTF8_LEFTWARDS_ARROW " B", NULL, "Any " UTF8_LEFTWARDS_ARROW " B", G_CALLBACK(conv_apply_as_selected_AnyfromB_cb)},
+
+ /* Apply as Not Selected */
+ { "/Apply as Filter/Not Selected/A_to_from_B", NULL, "A " UTF8_LEFT_RIGHT_ARROW " B", NULL, "A " UTF8_LEFT_RIGHT_ARROW " B", G_CALLBACK(conv_apply_as_not_selected_AtofromB_cb)},
+ { "/Apply as Filter/Not Selected/A_to_B", NULL, "A " UTF8_RIGHTWARDS_ARROW " B", NULL, "A " UTF8_RIGHTWARDS_ARROW " B", G_CALLBACK(conv_apply_as_not_selected_AtoB_cb)},
+ { "/Apply as Filter/Not Selected/A_from_B", NULL, "A " UTF8_LEFTWARDS_ARROW " B", NULL, "A " UTF8_LEFTWARDS_ARROW " B", G_CALLBACK(conv_apply_as_not_selected_AfromB_cb)},
+ { "/Apply as Filter/Not Selected/A_to_from_Any", NULL, "A " UTF8_LEFT_RIGHT_ARROW " Any",NULL, "A " UTF8_LEFT_RIGHT_ARROW " Any", G_CALLBACK(conv_apply_as_not_selected_AtofromAny_cb)},
+ { "/Apply as Filter/Not Selected/A_to_Any", NULL, "A " UTF8_RIGHTWARDS_ARROW " Any",NULL, "A " UTF8_LEFTWARDS_ARROW " Any", G_CALLBACK(conv_apply_as_not_selected_AtoAny_cb)},
+ { "/Apply as Filter/Not Selected/A_from_Any", NULL, "A " UTF8_LEFTWARDS_ARROW " Any",NULL, "A " UTF8_LEFTWARDS_ARROW " Any", G_CALLBACK(conv_apply_as_not_selected_AfromAny_cb)},
+ { "/Apply as Filter/Not Selected/Any_tofrom_B", NULL, "Any " UTF8_LEFT_RIGHT_ARROW " B",NULL, "Any " UTF8_LEFT_RIGHT_ARROW " B", G_CALLBACK(conv_apply_as_not_selected_AnytofromB_cb)},
+ { "/Apply as Filter/Not Selected/Any_to_B", NULL, "Any " UTF8_RIGHTWARDS_ARROW " B",NULL, "Any " UTF8_RIGHTWARDS_ARROW " B", G_CALLBACK(conv_apply_as_not_selected_AnytoB_cb)},
+ { "/Apply as Filter/Not Selected/Any_from_B", NULL, "Any " UTF8_LEFTWARDS_ARROW " B", NULL, "Any " UTF8_LEFTWARDS_ARROW " B", G_CALLBACK(conv_apply_as_not_selected_AnyfromB_cb)},
+
+ /* Apply as ... and Selected */
+ { "/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " and Selected/A_to_from_B", NULL, "A " UTF8_LEFT_RIGHT_ARROW " B", NULL, "A " UTF8_LEFT_RIGHT_ARROW " B", G_CALLBACK(conv_apply_and_selected_AtofromB_cb)},
+ { "/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " and Selected/A_to_B", NULL, "A " UTF8_RIGHTWARDS_ARROW " B", NULL, "A " UTF8_RIGHTWARDS_ARROW " B", G_CALLBACK(conv_apply_and_selected_AtoB_cb)},
+ { "/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " and Selected/A_from_B", NULL, "A " UTF8_LEFTWARDS_ARROW " B", NULL, "A " UTF8_LEFTWARDS_ARROW " B", G_CALLBACK(conv_apply_and_selected_AfromB_cb)},
+ { "/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " and Selected/A_to_from_Any", NULL, "A " UTF8_LEFT_RIGHT_ARROW " Any",NULL, "A " UTF8_LEFT_RIGHT_ARROW " Any",G_CALLBACK(conv_apply_and_selected_AtofromAny_cb)},
+ { "/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " and Selected/A_to_Any", NULL, "A " UTF8_RIGHTWARDS_ARROW " Any",NULL, "A " UTF8_LEFTWARDS_ARROW " Any", G_CALLBACK(conv_apply_and_selected_AtoAny_cb)},
+ { "/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " and Selected/A_from_Any", NULL, "A " UTF8_LEFTWARDS_ARROW " Any",NULL, "A " UTF8_LEFTWARDS_ARROW " Any", G_CALLBACK(conv_apply_and_selected_AfromAny_cb)},
+ { "/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " and Selected/Any_tofrom_B", NULL, "Any " UTF8_LEFT_RIGHT_ARROW " B",NULL, "Any " UTF8_LEFT_RIGHT_ARROW " B", G_CALLBACK(conv_apply_and_selected_AnytofromB_cb)},
+ { "/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " and Selected/Any_to_B", NULL, "Any " UTF8_RIGHTWARDS_ARROW " B",NULL, "Any " UTF8_RIGHTWARDS_ARROW " B", G_CALLBACK(conv_apply_and_selected_AnytoB_cb)},
+ { "/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " and Selected/Any_from_B", NULL, "Any " UTF8_LEFTWARDS_ARROW " B", NULL, "Any " UTF8_LEFTWARDS_ARROW " B", G_CALLBACK(conv_apply_and_selected_AnyfromB_cb)},
+
+ /* Apply as ... or Selected */
+ { "/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " or Selected/A_to_from_B", NULL, "A " UTF8_LEFT_RIGHT_ARROW " B", NULL, "A " UTF8_LEFT_RIGHT_ARROW " B", G_CALLBACK(conv_apply_or_selected_AtofromB_cb)},
+ { "/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " or Selected/A_to_B", NULL, "A " UTF8_RIGHTWARDS_ARROW " B", NULL, "A " UTF8_RIGHTWARDS_ARROW " B", G_CALLBACK(conv_apply_or_selected_AtoB_cb)},
+ { "/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " or Selected/A_from_B", NULL, "A " UTF8_LEFTWARDS_ARROW " B", NULL, "A " UTF8_LEFTWARDS_ARROW " B", G_CALLBACK(conv_apply_or_selected_AfromB_cb)},
+ { "/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " or Selected/A_to_from_Any", NULL, "A " UTF8_LEFT_RIGHT_ARROW " Any",NULL, "A " UTF8_LEFT_RIGHT_ARROW " Any",G_CALLBACK(conv_apply_or_selected_AtofromAny_cb)},
+ { "/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " or Selected/A_to_Any", NULL, "A " UTF8_RIGHTWARDS_ARROW " Any",NULL, "A " UTF8_LEFTWARDS_ARROW " Any", G_CALLBACK(conv_apply_or_selected_AtoAny_cb)},
+ { "/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " or Selected/A_from_Any", NULL, "A " UTF8_LEFTWARDS_ARROW " Any",NULL, "A " UTF8_LEFTWARDS_ARROW " Any", G_CALLBACK(conv_apply_or_selected_AfromAny_cb)},
+ { "/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " or Selected/Any_tofrom_B", NULL, "Any " UTF8_LEFT_RIGHT_ARROW " B",NULL, "Any " UTF8_LEFT_RIGHT_ARROW " B", G_CALLBACK(conv_apply_or_selected_AnytofromB_cb)},
+ { "/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " or Selected/Any_to_B", NULL, "Any " UTF8_RIGHTWARDS_ARROW " B",NULL, "Any " UTF8_RIGHTWARDS_ARROW " B", G_CALLBACK(conv_apply_or_selected_AnytoB_cb)},
+ { "/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " or Selected/Any_from_B", NULL, "Any " UTF8_LEFTWARDS_ARROW " B", NULL, "Any " UTF8_LEFTWARDS_ARROW " B", G_CALLBACK(conv_apply_or_selected_AnyfromB_cb)},
+
+ /* Apply as ... and not Selected */
+ { "/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " and not Selected/A_to_from_B", NULL, "A " UTF8_LEFT_RIGHT_ARROW " B", NULL, "A " UTF8_LEFT_RIGHT_ARROW " B", G_CALLBACK(conv_apply_and_not_selected_AtofromB_cb)},
+ { "/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " and not Selected/A_to_B", NULL, "A " UTF8_RIGHTWARDS_ARROW " B", NULL, "A " UTF8_RIGHTWARDS_ARROW " B", G_CALLBACK(conv_apply_and_not_selected_AtoB_cb)},
+ { "/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " and not Selected/A_from_B", NULL, "A " UTF8_LEFTWARDS_ARROW " B", NULL, "A " UTF8_LEFTWARDS_ARROW " B", G_CALLBACK(conv_apply_and_not_selected_AfromB_cb)},
+ { "/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " and not Selected/A_to_from_Any", NULL, "A " UTF8_LEFT_RIGHT_ARROW " Any",NULL, "A " UTF8_LEFT_RIGHT_ARROW " Any",G_CALLBACK(conv_apply_and_not_selected_AtofromAny_cb)},
+ { "/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " and not Selected/A_to_Any", NULL, "A " UTF8_RIGHTWARDS_ARROW " Any",NULL, "A " UTF8_LEFTWARDS_ARROW " Any", G_CALLBACK(conv_apply_and_not_selected_AtoAny_cb)},
+ { "/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " and not Selected/A_from_Any", NULL, "A " UTF8_LEFTWARDS_ARROW " Any",NULL, "A " UTF8_LEFTWARDS_ARROW " Any", G_CALLBACK(conv_apply_and_not_selected_AfromAny_cb)},
+ { "/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " and not Selected/Any_tofrom_B", NULL, "Any " UTF8_LEFT_RIGHT_ARROW " B",NULL, "Any " UTF8_LEFT_RIGHT_ARROW " B", G_CALLBACK(conv_apply_and_not_selected_AnytofromB_cb)},
+ { "/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " and not Selected/Any_to_B", NULL, "Any " UTF8_RIGHTWARDS_ARROW " B",NULL, "Any " UTF8_RIGHTWARDS_ARROW " B", G_CALLBACK(conv_apply_and_not_selected_AnytoB_cb)},
+ { "/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " and not Selected/Any_from_B", NULL, "Any " UTF8_LEFTWARDS_ARROW " B", NULL, "Any " UTF8_LEFTWARDS_ARROW " B", G_CALLBACK(conv_apply_and_not_selected_AnyfromB_cb)},
+
+ /* Apply as ... or not Selected */
+ { "/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " or not Selected/A_to_from_B", NULL, "A " UTF8_LEFT_RIGHT_ARROW " B", NULL, "A " UTF8_LEFT_RIGHT_ARROW " B", G_CALLBACK(conv_apply_or_not_selected_AtofromB_cb)},
+ { "/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " or not Selected/A_to_B", NULL, "A " UTF8_RIGHTWARDS_ARROW " B", NULL, "A " UTF8_RIGHTWARDS_ARROW " B", G_CALLBACK(conv_apply_or_not_selected_AtoB_cb)},
+ { "/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " or not Selected/A_from_B", NULL, "A " UTF8_LEFTWARDS_ARROW " B", NULL, "A " UTF8_LEFTWARDS_ARROW " B", G_CALLBACK(conv_apply_or_not_selected_AfromB_cb)},
+ { "/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " or not Selected/A_to_from_Any", NULL, "A " UTF8_LEFT_RIGHT_ARROW " Any",NULL, "A " UTF8_LEFT_RIGHT_ARROW " Any", G_CALLBACK(conv_apply_or_not_selected_AtofromAny_cb)},
+ { "/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " or not Selected/A_to_Any", NULL, "A " UTF8_RIGHTWARDS_ARROW " Any",NULL, "A " UTF8_LEFTWARDS_ARROW " Any", G_CALLBACK(conv_apply_or_not_selected_AtoAny_cb)},
+ { "/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " or not Selected/A_from_Any", NULL, "A " UTF8_LEFTWARDS_ARROW " Any",NULL, "A " UTF8_LEFTWARDS_ARROW " Any", G_CALLBACK(conv_apply_or_not_selected_AfromAny_cb)},
+ { "/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " or not Selected/Any_tofrom_B", NULL, "Any " UTF8_LEFT_RIGHT_ARROW " B",NULL, "Any " UTF8_LEFT_RIGHT_ARROW " B", G_CALLBACK(conv_apply_or_not_selected_AnytofromB_cb)},
+ { "/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " or not Selected/Any_to_B", NULL, "Any " UTF8_RIGHTWARDS_ARROW " B",NULL, "Any " UTF8_RIGHTWARDS_ARROW " B", G_CALLBACK(conv_apply_or_not_selected_AnytoB_cb)},
+ { "/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " or not Selected/Any_from_B", NULL, "Any " UTF8_LEFTWARDS_ARROW " B", NULL, "Any " UTF8_LEFTWARDS_ARROW " B", G_CALLBACK(conv_apply_or_not_selected_AnyfromB_cb)},
+
+ /* Prepare a */
+ { "/Prepare a Filter/Selected", NULL, "Selected", NULL, NULL, NULL },
+ { "/Prepare a Filter/Not Selected", NULL, "Not Selected", NULL, NULL, NULL },
+ { "/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " and Selected", NULL, UTF8_HORIZONTAL_ELLIPSIS " and Selected", NULL, NULL, NULL },
+ { "/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " or Selected", NULL, UTF8_HORIZONTAL_ELLIPSIS " or Selected", NULL, NULL, NULL },
+ { "/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " and not Selected", NULL, UTF8_HORIZONTAL_ELLIPSIS " and not Selected", NULL, NULL, NULL },
+ { "/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " or not Selected", NULL, UTF8_HORIZONTAL_ELLIPSIS " or not Selected", NULL, NULL, NULL },
+
+ /* Prepare as Selected */
+ { "/Prepare a Filter/Selected/A_to_from_B", NULL, "A " UTF8_LEFT_RIGHT_ARROW " B", NULL, "A " UTF8_LEFT_RIGHT_ARROW " B", G_CALLBACK(conv_prepare_as_selected_AtofromB_cb)},
+ { "/Prepare a Filter/Selected/A_to_B", NULL, "A " UTF8_RIGHTWARDS_ARROW " B", NULL, "A " UTF8_RIGHTWARDS_ARROW " B", G_CALLBACK(conv_prepare_as_selected_AtoB_cb)},
+ { "/Prepare a Filter/Selected/A_from_B", NULL, "A " UTF8_LEFTWARDS_ARROW " B", NULL, "A " UTF8_LEFTWARDS_ARROW " B", G_CALLBACK(conv_prepare_as_selected_AfromB_cb)},
+ { "/Prepare a Filter/Selected/A_to_from_Any", NULL, "A " UTF8_LEFT_RIGHT_ARROW " Any",NULL, "A " UTF8_LEFT_RIGHT_ARROW " Any", G_CALLBACK(conv_prepare_as_selected_AtofromAny_cb)},
+ { "/Prepare a Filter/Selected/A_to_Any", NULL, "A " UTF8_RIGHTWARDS_ARROW " Any",NULL, "A " UTF8_LEFTWARDS_ARROW " Any", G_CALLBACK(conv_prepare_as_selected_AtoAny_cb)},
+ { "/Prepare a Filter/Selected/A_from_Any", NULL, "A " UTF8_LEFTWARDS_ARROW " Any",NULL, "A " UTF8_LEFTWARDS_ARROW " Any", G_CALLBACK(conv_prepare_as_selected_AfromAny_cb)},
+ { "/Prepare a Filter/Selected/Any_tofrom_B", NULL, "Any " UTF8_LEFT_RIGHT_ARROW " B",NULL, "Any " UTF8_LEFT_RIGHT_ARROW " B", G_CALLBACK(conv_prepare_as_selected_AnytofromB_cb)},
+ { "/Prepare a Filter/Selected/Any_to_B", NULL, "Any " UTF8_RIGHTWARDS_ARROW " B",NULL, "Any " UTF8_RIGHTWARDS_ARROW " B", G_CALLBACK(conv_prepare_as_selected_AnytoB_cb)},
+ { "/Prepare a Filter/Selected/Any_from_B", NULL, "Any " UTF8_LEFTWARDS_ARROW " B", NULL, "Any " UTF8_LEFTWARDS_ARROW " B", G_CALLBACK(conv_prepare_as_selected_AnyfromB_cb)},
+
+ /* Prepare a Not Selected */
+ { "/Prepare a Filter/Not Selected/A_to_from_B", NULL, "A " UTF8_LEFT_RIGHT_ARROW " B", NULL, "A " UTF8_LEFT_RIGHT_ARROW " B", G_CALLBACK(conv_prepare_as_not_selected_AtofromB_cb)},
+ { "/Prepare a Filter/Not Selected/A_to_B", NULL, "A " UTF8_RIGHTWARDS_ARROW " B", NULL, "A " UTF8_RIGHTWARDS_ARROW " B", G_CALLBACK(conv_prepare_as_not_selected_AtoB_cb)},
+ { "/Prepare a Filter/Not Selected/A_from_B", NULL, "A " UTF8_LEFTWARDS_ARROW " B", NULL, "A " UTF8_LEFTWARDS_ARROW " B", G_CALLBACK(conv_prepare_as_not_selected_AfromB_cb)},
+ { "/Prepare a Filter/Not Selected/A_to_from_Any", NULL, "A " UTF8_LEFT_RIGHT_ARROW " Any",NULL, "A " UTF8_LEFT_RIGHT_ARROW " Any", G_CALLBACK(conv_prepare_as_not_selected_AtofromAny_cb)},
+ { "/Prepare a Filter/Not Selected/A_to_Any", NULL, "A " UTF8_RIGHTWARDS_ARROW " Any",NULL, "A " UTF8_LEFTWARDS_ARROW " Any", G_CALLBACK(conv_prepare_as_not_selected_AtoAny_cb)},
+ { "/Prepare a Filter/Not Selected/A_from_Any", NULL, "A " UTF8_LEFTWARDS_ARROW " Any",NULL, "A " UTF8_LEFTWARDS_ARROW " Any", G_CALLBACK(conv_prepare_as_not_selected_AfromAny_cb)},
+ { "/Prepare a Filter/Not Selected/Any_tofrom_B", NULL, "Any " UTF8_LEFT_RIGHT_ARROW " B",NULL, "Any " UTF8_LEFT_RIGHT_ARROW " B", G_CALLBACK(conv_prepare_as_not_selected_AnytofromB_cb)},
+ { "/Prepare a Filter/Not Selected/Any_to_B", NULL, "Any " UTF8_RIGHTWARDS_ARROW " B",NULL, "Any " UTF8_RIGHTWARDS_ARROW " B", G_CALLBACK(conv_prepare_as_not_selected_AnytoB_cb)},
+ { "/Prepare a Filter/Not Selected/Any_from_B", NULL, "Any " UTF8_LEFTWARDS_ARROW " B", NULL, "Any " UTF8_LEFTWARDS_ARROW " B", G_CALLBACK(conv_prepare_as_not_selected_AnyfromB_cb)},
+
+ /* Prepare a ... and Selected */
+ { "/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " and Selected/A_to_from_B", NULL, "A " UTF8_LEFT_RIGHT_ARROW " B", NULL, "A " UTF8_LEFT_RIGHT_ARROW " B", G_CALLBACK(conv_prepare_and_selected_AtofromB_cb)},
+ { "/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " and Selected/A_to_B", NULL, "A " UTF8_RIGHTWARDS_ARROW " B", NULL, "A " UTF8_RIGHTWARDS_ARROW " B", G_CALLBACK(conv_prepare_and_selected_AtoB_cb)},
+ { "/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " and Selected/A_from_B", NULL, "A " UTF8_LEFTWARDS_ARROW " B", NULL, "A " UTF8_LEFTWARDS_ARROW " B", G_CALLBACK(conv_prepare_and_selected_AfromB_cb)},
+ { "/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " and Selected/A_to_from_Any", NULL, "A " UTF8_LEFT_RIGHT_ARROW " Any",NULL, "A " UTF8_LEFT_RIGHT_ARROW " Any", G_CALLBACK(conv_prepare_and_selected_AtofromAny_cb)},
+ { "/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " and Selected/A_to_Any", NULL, "A " UTF8_RIGHTWARDS_ARROW " Any",NULL, "A " UTF8_LEFTWARDS_ARROW " Any", G_CALLBACK(conv_prepare_and_selected_AtoAny_cb)},
+ { "/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " and Selected/A_from_Any", NULL, "A " UTF8_LEFTWARDS_ARROW " Any",NULL, "A " UTF8_LEFTWARDS_ARROW " Any", G_CALLBACK(conv_prepare_and_selected_AfromAny_cb)},
+ { "/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " and Selected/Any_tofrom_B", NULL, "Any " UTF8_LEFT_RIGHT_ARROW " B",NULL, "Any " UTF8_LEFT_RIGHT_ARROW " B", G_CALLBACK(conv_prepare_and_selected_AnytofromB_cb)},
+ { "/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " and Selected/Any_to_B", NULL, "Any " UTF8_RIGHTWARDS_ARROW " B",NULL, "Any " UTF8_RIGHTWARDS_ARROW " B", G_CALLBACK(conv_prepare_and_selected_AnytoB_cb)},
+ { "/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " and Selected/Any_from_B", NULL, "Any " UTF8_LEFTWARDS_ARROW " B", NULL, "Any " UTF8_LEFTWARDS_ARROW " B", G_CALLBACK(conv_prepare_and_selected_AnyfromB_cb)},
+
+ /* Prepare a ... or Selected */
+ { "/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " or Selected/A_to_from_B", NULL, "A " UTF8_LEFT_RIGHT_ARROW " B", NULL, "A " UTF8_LEFT_RIGHT_ARROW " B", G_CALLBACK(conv_prepare_or_selected_AtofromB_cb)},
+ { "/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " or Selected/A_to_B", NULL, "A " UTF8_RIGHTWARDS_ARROW " B", NULL, "A " UTF8_RIGHTWARDS_ARROW " B", G_CALLBACK(conv_prepare_or_selected_AtoB_cb)},
+ { "/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " or Selected/A_from_B", NULL, "A " UTF8_LEFTWARDS_ARROW " B", NULL, "A " UTF8_LEFTWARDS_ARROW " B", G_CALLBACK(conv_prepare_or_selected_AfromB_cb)},
+ { "/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " or Selected/A_to_from_Any", NULL, "A " UTF8_LEFT_RIGHT_ARROW " Any",NULL, "A " UTF8_LEFT_RIGHT_ARROW " Any", G_CALLBACK(conv_prepare_or_selected_AtofromAny_cb)},
+ { "/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " or Selected/A_to_Any", NULL, "A " UTF8_RIGHTWARDS_ARROW " Any",NULL, "A " UTF8_LEFTWARDS_ARROW " Any", G_CALLBACK(conv_prepare_or_selected_AtoAny_cb)},
+ { "/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " or Selected/A_from_Any", NULL, "A " UTF8_LEFTWARDS_ARROW " Any",NULL, "A " UTF8_LEFTWARDS_ARROW " Any", G_CALLBACK(conv_prepare_or_selected_AfromAny_cb)},
+ { "/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " or Selected/Any_tofrom_B", NULL, "Any " UTF8_LEFT_RIGHT_ARROW " B",NULL, "Any " UTF8_LEFT_RIGHT_ARROW " B", G_CALLBACK(conv_prepare_or_selected_AnytofromB_cb)},
+ { "/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " or Selected/Any_to_B", NULL, "Any " UTF8_RIGHTWARDS_ARROW " B",NULL, "Any " UTF8_RIGHTWARDS_ARROW " B", G_CALLBACK(conv_prepare_or_selected_AnytoB_cb)},
+ { "/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " or Selected/Any_from_B", NULL, "Any " UTF8_LEFTWARDS_ARROW " B", NULL, "Any " UTF8_LEFTWARDS_ARROW " B", G_CALLBACK(conv_prepare_or_selected_AnyfromB_cb)},
+
+ /* Prepare a ... and not Selected */
+ { "/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " and not Selected/A_to_from_B", NULL, "A " UTF8_LEFT_RIGHT_ARROW " B", NULL, "A " UTF8_LEFT_RIGHT_ARROW " B", G_CALLBACK(conv_prepare_and_not_selected_AtofromB_cb)},
+ { "/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " and not Selected/A_to_B", NULL, "A " UTF8_RIGHTWARDS_ARROW " B", NULL, "A " UTF8_RIGHTWARDS_ARROW " B", G_CALLBACK(conv_prepare_and_not_selected_AtoB_cb)},
+ { "/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " and not Selected/A_from_B", NULL, "A " UTF8_LEFTWARDS_ARROW " B", NULL, "A " UTF8_LEFTWARDS_ARROW " B", G_CALLBACK(conv_prepare_and_not_selected_AfromB_cb)},
+ { "/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " and not Selected/A_to_from_Any",NULL, "A " UTF8_LEFT_RIGHT_ARROW " Any",NULL, "A " UTF8_LEFT_RIGHT_ARROW " Any", G_CALLBACK(conv_prepare_and_not_selected_AtofromAny_cb)},
+ { "/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " and not Selected/A_to_Any", NULL, "A " UTF8_RIGHTWARDS_ARROW " Any",NULL, "A " UTF8_LEFTWARDS_ARROW " Any", G_CALLBACK(conv_prepare_and_not_selected_AtoAny_cb)},
+ { "/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " and not Selected/A_from_Any", NULL, "A " UTF8_LEFTWARDS_ARROW " Any",NULL, "A " UTF8_LEFTWARDS_ARROW " Any", G_CALLBACK(conv_prepare_and_not_selected_AfromAny_cb)},
+ { "/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " and not Selected/Any_tofrom_B", NULL, "Any " UTF8_LEFT_RIGHT_ARROW " B",NULL, "Any " UTF8_LEFT_RIGHT_ARROW " B", G_CALLBACK(conv_prepare_and_not_selected_AnytofromB_cb)},
+ { "/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " and not Selected/Any_to_B", NULL, "Any " UTF8_RIGHTWARDS_ARROW " B",NULL, "Any " UTF8_RIGHTWARDS_ARROW " B", G_CALLBACK(conv_prepare_and_not_selected_AnytoB_cb)},
+ { "/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " and not Selected/Any_from_B", NULL, "Any " UTF8_LEFTWARDS_ARROW " B", NULL, "Any " UTF8_LEFTWARDS_ARROW " B", G_CALLBACK(conv_prepare_and_not_selected_AnyfromB_cb)},
+
+ /* Prepare a ... or not Selected */
+ { "/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " or not Selected/A_to_from_B", NULL, "A " UTF8_LEFT_RIGHT_ARROW " B", NULL, "A " UTF8_LEFT_RIGHT_ARROW " B", G_CALLBACK(conv_prepare_or_not_selected_AtofromB_cb)},
+ { "/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " or not Selected/A_to_B", NULL, "A " UTF8_RIGHTWARDS_ARROW " B", NULL, "A " UTF8_RIGHTWARDS_ARROW " B", G_CALLBACK(conv_prepare_or_not_selected_AtoB_cb)},
+ { "/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " or not Selected/A_from_B", NULL, "A " UTF8_LEFTWARDS_ARROW " B", NULL, "A " UTF8_LEFTWARDS_ARROW " B", G_CALLBACK(conv_prepare_or_not_selected_AfromB_cb)},
+ { "/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " or not Selected/A_to_from_Any", NULL, "A " UTF8_LEFT_RIGHT_ARROW " Any",NULL, "A " UTF8_LEFT_RIGHT_ARROW " Any", G_CALLBACK(conv_prepare_or_not_selected_AtofromAny_cb)},
+ { "/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " or not Selected/A_to_Any", NULL, "A " UTF8_RIGHTWARDS_ARROW " Any",NULL, "A " UTF8_LEFTWARDS_ARROW " Any", G_CALLBACK(conv_prepare_or_not_selected_AtoAny_cb)},
+ { "/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " or not Selected/A_from_Any", NULL, "A " UTF8_LEFTWARDS_ARROW " Any",NULL, "A " UTF8_LEFTWARDS_ARROW " Any", G_CALLBACK(conv_prepare_or_not_selected_AfromAny_cb)},
+ { "/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " or not Selected/Any_tofrom_B", NULL, "Any " UTF8_LEFT_RIGHT_ARROW " B",NULL, "Any " UTF8_LEFT_RIGHT_ARROW " B", G_CALLBACK(conv_prepare_or_not_selected_AnytofromB_cb)},
+ { "/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " or not Selected/Any_to_B", NULL, "Any " UTF8_RIGHTWARDS_ARROW " B",NULL, "Any " UTF8_RIGHTWARDS_ARROW " B", G_CALLBACK(conv_prepare_or_not_selected_AnytoB_cb)},
+ { "/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " or not Selected/Any_from_B", NULL, "Any " UTF8_LEFTWARDS_ARROW " B", NULL, "Any " UTF8_LEFTWARDS_ARROW " B", G_CALLBACK(conv_prepare_or_not_selected_AnyfromB_cb)},
+
+ /* Find packet*/
+ { "/Find Packet/Find Packet", NULL, "Find Packet", NULL, NULL, NULL },
+ { "/Find Packet/Find Next", NULL, "Find Next", NULL, NULL, NULL },
+ { "/Find Packet/Find Previous", NULL, "Find Previous", NULL, NULL, NULL },
+
+ /* Find packet*/
+ { "/Find Packet/Find Packet/A_to_from_B", NULL, "A " UTF8_LEFT_RIGHT_ARROW " B", NULL, "A " UTF8_LEFT_RIGHT_ARROW " B", G_CALLBACK(conv_find_AtofromB_cb)},
+ { "/Find Packet/Find Packet/A_to_B", NULL, "A " UTF8_RIGHTWARDS_ARROW " B", NULL, "A " UTF8_RIGHTWARDS_ARROW " B", G_CALLBACK(conv_find_AtoB_cb)},
+ { "/Find Packet/Find Packet/A_from_B", NULL, "A " UTF8_LEFTWARDS_ARROW " B", NULL, "A " UTF8_LEFTWARDS_ARROW " B", G_CALLBACK(conv_find_AfromB_cb)},
+ { "/Find Packet/Find Packet/A_to_from_Any", NULL, "A " UTF8_LEFT_RIGHT_ARROW " Any",NULL, "A " UTF8_LEFT_RIGHT_ARROW " Any",G_CALLBACK(conv_find_AtofromAny_cb)},
+ { "/Find Packet/Find Packet/A_to_Any", NULL, "A " UTF8_RIGHTWARDS_ARROW " Any",NULL, "A " UTF8_LEFTWARDS_ARROW " Any", G_CALLBACK(conv_find_AtoAny_cb)},
+ { "/Find Packet/Find Packet/A_from_Any", NULL, "A " UTF8_LEFTWARDS_ARROW " Any",NULL, "A " UTF8_LEFTWARDS_ARROW " Any", G_CALLBACK(conv_find_AfromAny_cb)},
+ { "/Find Packet/Find Packet/Any_tofrom_B", NULL, "Any " UTF8_LEFT_RIGHT_ARROW " B",NULL, "Any " UTF8_LEFT_RIGHT_ARROW " B", G_CALLBACK(conv_find_AnytofromB_cb)},
+ { "/Find Packet/Find Packet/Any_to_B", NULL, "Any " UTF8_RIGHTWARDS_ARROW " B",NULL, "Any " UTF8_RIGHTWARDS_ARROW " B", G_CALLBACK(conv_find_AnytoB_cb)},
+ { "/Find Packet/Find Packet/Any_from_B", NULL, "Any " UTF8_LEFTWARDS_ARROW " B", NULL, "Any " UTF8_LEFTWARDS_ARROW " B", G_CALLBACK(conv_find_AnyfromB_cb)},
+
+ /* Find Next*/
+ { "/Find Packet/Find Next/A_to_from_B", NULL, "A " UTF8_LEFT_RIGHT_ARROW " B", NULL, "A " UTF8_LEFT_RIGHT_ARROW " B", G_CALLBACK(conv_find_next_AtofromB_cb)},
+ { "/Find Packet/Find Next/A_to_B", NULL, "A " UTF8_RIGHTWARDS_ARROW " B", NULL, "A " UTF8_RIGHTWARDS_ARROW " B", G_CALLBACK(conv_find_next_AtoB_cb)},
+ { "/Find Packet/Find Next/A_from_B", NULL, "A " UTF8_LEFTWARDS_ARROW " B", NULL, "A " UTF8_LEFTWARDS_ARROW " B", G_CALLBACK(conv_find_next_AfromB_cb)},
+ { "/Find Packet/Find Next/A_to_from_Any", NULL, "A " UTF8_LEFT_RIGHT_ARROW " Any",NULL, "A " UTF8_LEFT_RIGHT_ARROW " Any",G_CALLBACK(conv_find_next_AtofromAny_cb)},
+ { "/Find Packet/Find Next/A_to_Any", NULL, "A " UTF8_RIGHTWARDS_ARROW " Any",NULL, "A " UTF8_LEFTWARDS_ARROW " Any", G_CALLBACK(conv_find_next_AtoAny_cb)},
+ { "/Find Packet/Find Next/A_from_Any", NULL, "A " UTF8_LEFTWARDS_ARROW " Any",NULL, "A " UTF8_LEFTWARDS_ARROW " Any", G_CALLBACK(conv_find_next_AfromAny_cb)},
+ { "/Find Packet/Find Next/Any_tofrom_B", NULL, "Any " UTF8_LEFT_RIGHT_ARROW " B",NULL, "Any " UTF8_LEFT_RIGHT_ARROW " B", G_CALLBACK(conv_find_next_AnytofromB_cb)},
+ { "/Find Packet/Find Next/Any_to_B", NULL, "Any " UTF8_RIGHTWARDS_ARROW " B",NULL, "Any " UTF8_RIGHTWARDS_ARROW " B", G_CALLBACK(conv_find_next_AnytoB_cb)},
+ { "/Find Packet/Find Next/Any_from_B", NULL, "Any " UTF8_LEFTWARDS_ARROW " B", NULL, "Any " UTF8_LEFTWARDS_ARROW " B", G_CALLBACK(conv_find_next_AnyfromB_cb)},
+
+ /* Find packet*/
+ { "/Find Packet/Find Previous/A_to_from_B", NULL, "A " UTF8_LEFT_RIGHT_ARROW " B", NULL, "A " UTF8_LEFT_RIGHT_ARROW " B", G_CALLBACK(conv_find_previous_AtofromB_cb)},
+ { "/Find Packet/Find Previous/A_to_B", NULL, "A " UTF8_RIGHTWARDS_ARROW " B", NULL, "A " UTF8_RIGHTWARDS_ARROW " B", G_CALLBACK(conv_find_previous_AtoB_cb)},
+ { "/Find Packet/Find Previous/A_from_B", NULL, "A " UTF8_LEFTWARDS_ARROW " B", NULL, "A " UTF8_LEFTWARDS_ARROW " B", G_CALLBACK(conv_find_previous_AfromB_cb)},
+ { "/Find Packet/Find Previous/A_to_from_Any", NULL, "A " UTF8_LEFT_RIGHT_ARROW " Any",NULL, "A " UTF8_LEFT_RIGHT_ARROW " Any",G_CALLBACK(conv_find_previous_AtofromAny_cb)},
+ { "/Find Packet/Find Previous/A_to_Any", NULL, "A " UTF8_RIGHTWARDS_ARROW " Any",NULL, "A " UTF8_LEFTWARDS_ARROW " Any", G_CALLBACK(conv_find_previous_AtoAny_cb)},
+ { "/Find Packet/Find Previous/A_from_Any", NULL, "A " UTF8_LEFTWARDS_ARROW " Any",NULL, "A " UTF8_LEFTWARDS_ARROW " Any", G_CALLBACK(conv_find_previous_AfromAny_cb)},
+ { "/Find Packet/Find Previous/Any_tofrom_B", NULL, "Any " UTF8_LEFT_RIGHT_ARROW " B",NULL, "Any " UTF8_LEFT_RIGHT_ARROW " B", G_CALLBACK(conv_find_previous_AnytofromB_cb)},
+ { "/Find Packet/Find Previous/Any_to_B", NULL, "Any " UTF8_RIGHTWARDS_ARROW " B",NULL, "Any " UTF8_RIGHTWARDS_ARROW " B", G_CALLBACK(conv_find_previous_AnytoB_cb)},
+ { "/Find Packet/Find Previous/Any_from_B", NULL, "Any " UTF8_LEFTWARDS_ARROW " B", NULL, "Any " UTF8_LEFTWARDS_ARROW " B", G_CALLBACK(conv_find_previous_AnyfromB_cb)},
+
+ /* Colorize Conversation */
+ { "/Colorize Conversation/A_to_from_B", NULL, "A " UTF8_LEFT_RIGHT_ARROW " B", NULL, "A " UTF8_LEFT_RIGHT_ARROW " B", G_CALLBACK(conv_color_AtofromB_cb)},
+ { "/Colorize Conversation/A_to_B", NULL, "A " UTF8_RIGHTWARDS_ARROW " B", NULL, "A " UTF8_RIGHTWARDS_ARROW " B", G_CALLBACK(conv_color_AtoB_cb)},
+ { "/Colorize Conversation/A_from_B", NULL, "A " UTF8_LEFTWARDS_ARROW " B", NULL, "A " UTF8_LEFTWARDS_ARROW " B", G_CALLBACK(conv_color_AfromB_cb)},
+ { "/Colorize Conversation/A_to_from_Any", NULL, "A " UTF8_LEFT_RIGHT_ARROW " Any",NULL, "A " UTF8_LEFT_RIGHT_ARROW " Any",G_CALLBACK(conv_color_AtofromAny_cb)},
+ { "/Colorize Conversation/A_to_Any", NULL, "A " UTF8_RIGHTWARDS_ARROW " Any",NULL, "A " UTF8_LEFTWARDS_ARROW " Any", G_CALLBACK(conv_color_AtoAny_cb)},
+ { "/Colorize Conversation/A_from_Any", NULL, "A " UTF8_LEFTWARDS_ARROW " Any",NULL, "A " UTF8_LEFTWARDS_ARROW " Any", G_CALLBACK(conv_color_AfromAny_cb)},
+ { "/Colorize Conversation/Any_tofrom_B", NULL, "Any " UTF8_LEFT_RIGHT_ARROW " B",NULL, "Any " UTF8_LEFT_RIGHT_ARROW " B", G_CALLBACK(conv_color_AnytofromB_cb)},
+ { "/Colorize Conversation/Any_to_B", NULL, "Any " UTF8_RIGHTWARDS_ARROW " B",NULL, "Any " UTF8_RIGHTWARDS_ARROW " B", G_CALLBACK(conv_color_AnytoB_cb)},
+ { "/Colorize Conversation/Any_from_B", NULL, "Any " UTF8_LEFTWARDS_ARROW " B", NULL, "Any " UTF8_LEFTWARDS_ARROW " B", G_CALLBACK(conv_color_AnyfromB_cb)},
+
+};
+
+static void
+ct_create_popup_menu(conversations_table *ct)
+{
+ GtkUIManager *ui_manager;
+ GtkActionGroup *action_group;
+ GError *error = NULL;
+
+ action_group = gtk_action_group_new ("ConvActionGroup");
+ gtk_action_group_add_actions (action_group, /* the action group */
+ (gpointer)conv_filter_menu_entries, /* an array of action descriptions */
+ G_N_ELEMENTS(conv_filter_menu_entries), /* the number of entries */
+ (gpointer)ct); /* data to pass to the action callbacks */
+
+ ui_manager = gtk_ui_manager_new ();
+ gtk_ui_manager_insert_action_group (ui_manager, action_group, 0);
+ gtk_ui_manager_add_ui_from_string (ui_manager,ui_desc_conv_filter_popup, -1, &error);
+ if (error != NULL)
+ {
+ fprintf (stderr, "Warning: building conversation filter popup failed: %s\n",
+ error->message);
+ g_error_free (error);
+ error = NULL;
+ }
+ ct->menu = gtk_ui_manager_get_widget(ui_manager, "/ConversationFilterPopup");
+
+ g_signal_connect(ct->table, "button_press_event", G_CALLBACK(ct_show_popup_menu_cb), ct);
+
+}
+
+/* Draw/refresh the address fields of a single entry at the specified index */
+static void
+get_ct_table_address(conversations_table *ct, conv_t *conv, char **entries)
+{
+ char *port;
+ guint32 pt;
+
+ if(!ct->resolve_names)
+ entries[0] = ep_address_to_str(&conv->src_address);
+ else {
+ entries[0] = (char *)get_addr_name(&conv->src_address);
+ }
+
+ pt = conv->port_type;
+ if(!ct->resolve_names) pt = PT_NONE;
+ switch(pt) {
+ case(PT_TCP):
+ entries[1] = get_tcp_port(conv->src_port);
+ break;
+ case(PT_UDP):
+ entries[1] = get_udp_port(conv->src_port);
+ break;
+ case(PT_SCTP):
+ entries[1] = get_sctp_port(conv->src_port);
+ break;
+ default:
+ port=ct_port_to_str(conv->port_type, conv->src_port);
+ entries[1] = port?port:"";
+ }
+
+ if(!ct->resolve_names)
+ entries[2]=ep_address_to_str(&conv->dst_address);
+ else {
+ entries[2]=(char *)get_addr_name(&conv->dst_address);
+ }
+
+ switch(pt) {
+ case(PT_TCP):
+ entries[3]=get_tcp_port(conv->dst_port);
+ break;
+ case(PT_UDP):
+ entries[3]=get_udp_port(conv->dst_port);
+ break;
+ case(PT_SCTP):
+ entries[3]=get_sctp_port(conv->dst_port);
+ break;
+ default:
+ port=ct_port_to_str(conv->port_type, conv->dst_port);
+ entries[3]=port?port:"";
+ }
+}
+
+/* Refresh the address fields of all entries in the list */
+static void
+draw_ct_table_addresses(conversations_table *ct)
+{
+ guint32 i;
+ char *entries[4];
+ GtkListStore *store;
+
+ if (!ct->num_conversations)
+ return;
+
+ store = GTK_LIST_STORE(gtk_tree_view_get_model(ct->table));
+ g_object_ref(store);
+ gtk_tree_view_set_model(GTK_TREE_VIEW(ct->table), NULL);
+
+ for(i=0;i<ct->num_conversations;i++){
+ conv_t *conv = &g_array_index(ct->conversations, conv_t, i);
+ if (!conv->iter_valid)
+ continue;
+ get_ct_table_address(ct, conv, entries);
+ gtk_list_store_set (store, &conv->iter,
+ SRC_ADR_COLUMN, entries[0],
+ SRC_PORT_COLUMN, entries[1],
+ DST_ADR_COLUMN, entries[2],
+ DST_PORT_COLUMN, entries[3],
+ -1);
+ }
+
+ gtk_tree_view_set_model(GTK_TREE_VIEW(ct->table), GTK_TREE_MODEL(store));
+ g_object_unref(store);
+}
+
+static void
+draw_ct_table_data(conversations_table *ct)
+{
+ guint32 i;
+ char title[256];
+ GtkListStore *store;
+ gboolean first = TRUE;
+
+ if (ct->page_lb) {
+ if(ct->num_conversations) {
+ g_snprintf(title, sizeof(title), "%s: %u", ct->name, ct->num_conversations);
+ } else {
+ g_snprintf(title, sizeof(title), "%s", ct->name);
+ }
+ gtk_label_set_text(GTK_LABEL(ct->page_lb), title);
+ gtk_widget_set_sensitive(ct->page_lb, ct->num_conversations);
+ } else {
+ if(ct->num_conversations) {
+ g_snprintf(title, sizeof(title), "%s Conversations: %u", ct->name, ct->num_conversations);
+ } else {
+ g_snprintf(title, sizeof(title), "%s Conversations", ct->name);
+ }
+ gtk_label_set_text(GTK_LABEL(ct->name_lb), title);
+ }
+
+ store = GTK_LIST_STORE(gtk_tree_view_get_model(ct->table));
+
+ for(i=0;i<ct->num_conversations;i++){
+ char start_time[COL_STR_LEN], duration[COL_STR_LEN],
+ txbps[COL_STR_LEN], rxbps[COL_STR_LEN];
+ char *tx_ptr, *rx_ptr;
+ double duration_s;
+ conv_t *conversation = &g_array_index(ct->conversations, conv_t, i);
+
+ if (!conversation->modified)
+ continue;
+
+ if (first) {
+ g_object_ref(store);
+ gtk_tree_view_set_model(GTK_TREE_VIEW(ct->table), NULL);
+
+ first = FALSE;
+ }
+ duration_s = nstime_to_sec(&conversation->stop_time) - nstime_to_sec(&conversation->start_time);
+ g_snprintf(start_time, COL_STR_LEN, "%.9f", nstime_to_sec(&conversation->start_time));
+ g_snprintf(duration, COL_STR_LEN, "%.4f", duration_s);
+
+ if (duration_s > 0 && conversation->tx_frames > 1) {
+ g_snprintf(txbps, COL_STR_LEN, "%.2f", (gint64) conversation->tx_bytes * 8 / duration_s);
+ tx_ptr = txbps;
+ } else {
+ tx_ptr = NO_BPS_STR;
+ }
+ if (duration_s > 0 && conversation->rx_frames > 1) {
+ g_snprintf(rxbps, COL_STR_LEN, "%.2f", (gint64) conversation->rx_bytes * 8 / duration_s);
+ rx_ptr = rxbps;
+ } else {
+ rx_ptr = NO_BPS_STR;
+ }
+ conversation->modified = FALSE;
+ if (!conversation->iter_valid) {
+ char *entries[4];
+
+ get_ct_table_address(ct, conversation, entries);
+ conversation->iter_valid = TRUE;
+ gtk_list_store_insert_with_values( store , &conversation->iter, G_MAXINT,
+ SRC_ADR_COLUMN, entries[0],
+ SRC_PORT_COLUMN, entries[1],
+ DST_ADR_COLUMN, entries[2],
+ DST_PORT_COLUMN, entries[3],
+ PACKETS_COLUMN, conversation->tx_frames+conversation->rx_frames,
+ BYTES_COLUMN, conversation->tx_bytes+conversation->rx_bytes,
+ PKT_AB_COLUMN, conversation->tx_frames,
+ BYTES_AB_COLUMN, conversation->tx_bytes,
+ PKT_BA_COLUMN, conversation->rx_frames,
+ BYTES_BA_COLUMN, conversation->rx_bytes,
+ START_COLUMN, start_time,
+ DURATION_COLUMN, duration,
+ BPS_AB_COLUMN, tx_ptr,
+ BPS_BA_COLUMN, rx_ptr,
+ INDEX_COLUMN, i,
+ -1);
+ }
+ else {
+ gtk_list_store_set (store, &conversation->iter,
+ PACKETS_COLUMN, conversation->tx_frames+conversation->rx_frames,
+ BYTES_COLUMN, conversation->tx_bytes+conversation->rx_bytes,
+ PKT_AB_COLUMN, conversation->tx_frames,
+ BYTES_AB_COLUMN, conversation->tx_bytes,
+ PKT_BA_COLUMN, conversation->rx_frames,
+ BYTES_BA_COLUMN, conversation->rx_bytes,
+ START_COLUMN, start_time,
+ DURATION_COLUMN, duration,
+ BPS_AB_COLUMN, tx_ptr,
+ BPS_BA_COLUMN, rx_ptr,
+ -1);
+ }
+ }
+ if (!first) {
+ if (!ct->fixed_col && ct->num_conversations >= 1000) {
+ /* finding the right size for a column isn't easy
+ * let it run in autosize a little (1000 is arbitrary)
+ * and then switch to fixed width.
+ */
+ ct->fixed_col = TRUE;
+
+ switch_to_fixed_col(ct->table);
+ }
+
+ gtk_tree_view_set_model(GTK_TREE_VIEW(ct->table), GTK_TREE_MODEL(store));
+ g_object_unref(store);
+ }
+}
+
+static void
+draw_ct_table_data_cb(void *arg)
+{
+ draw_ct_table_data(arg);
+}
+
+typedef struct {
+ int nb_cols;
+ gint columns_order[N_COLUMNS];
+ GString *CSV_str;
+ conversations_table *talkers;
+} csv_t;
+
+/* output in C locale */
+static gboolean
+csv_handle(GtkTreeModel *model, GtkTreePath *path _U_, GtkTreeIter *iter,
+ gpointer data)
+{
+ csv_t *csv = (csv_t *)data;
+ gchar *table_text;
+ int i;
+ unsigned idx;
+ conv_t *conv;
+ double duration_s;
+ guint64 value;
+
+ gtk_tree_model_get(model, iter, INDEX_COLUMN, &idx, -1);
+ conv=&g_array_index(csv->talkers->conversations, conv_t, idx);
+ duration_s = nstime_to_sec(&conv->stop_time) - nstime_to_sec(&conv->start_time);
+
+ for (i=0; i< csv->nb_cols; i++) {
+ if (i)
+ g_string_append(csv->CSV_str, ",");
+
+ switch(csv->columns_order[i]) {
+ case SRC_ADR_COLUMN:
+ case SRC_PORT_COLUMN:
+ case DST_ADR_COLUMN:
+ case DST_PORT_COLUMN:
+ gtk_tree_model_get(model, iter, csv->columns_order[i], &table_text, -1);
+ if (table_text) {
+ g_string_append_printf(csv->CSV_str, "\"%s\"", table_text);
+ g_free(table_text);
+ }
+ break;
+ case PACKETS_COLUMN:
+ case BYTES_COLUMN:
+ case PKT_AB_COLUMN:
+ case BYTES_AB_COLUMN:
+ case PKT_BA_COLUMN:
+ case BYTES_BA_COLUMN:
+ gtk_tree_model_get(model, iter, csv->columns_order[i], &value, -1);
+ g_string_append_printf(csv->CSV_str, "\"%" G_GINT64_MODIFIER "u\"", value);
+ break;
+ case START_COLUMN:
+ g_string_append_printf(csv->CSV_str, "\"%.9f\"", nstime_to_sec(&conv->start_time));
+ break;
+ case DURATION_COLUMN:
+ g_string_append_printf(csv->CSV_str, "\"%.4f\"", duration_s);
+ break;
+ case BPS_AB_COLUMN:
+ if (duration_s > 0 && conv->tx_frames > 1) {
+ g_string_append_printf(csv->CSV_str, "\"%.2f\"", (gint64) conv->tx_bytes * 8 / duration_s);
+ } else {
+ g_string_append(csv->CSV_str, "\"" NO_BPS_STR "\"");
+ }
+ break;
+ case BPS_BA_COLUMN:
+ if (duration_s > 0 && conv->rx_frames > 1) {
+ g_string_append_printf(csv->CSV_str, "\"%.2f\"", (gint64) conv->rx_bytes * 8 / duration_s);
+ } else {
+ g_string_append(csv->CSV_str, "\"" NO_BPS_STR "\"");
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ g_string_append(csv->CSV_str,"\n");
+
+ return FALSE;
+}
+
+
+static void
+copy_as_csv_cb(GtkWindow *copy_bt, gpointer data _U_)
+{
+ GtkClipboard *cb;
+ GList *columns, *list;
+ GtkTreeViewColumn *column;
+ GtkListStore *store;
+ csv_t csv;
+
+ csv.talkers=g_object_get_data(G_OBJECT(copy_bt), CONV_PTR_KEY);
+ if (!csv.talkers)
+ return;
+
+ csv.CSV_str = g_string_new("");
+
+ columns = gtk_tree_view_get_columns(GTK_TREE_VIEW(csv.talkers->table));
+ csv.nb_cols = 0;
+ list = columns;
+ while(columns) {
+ column = columns->data;
+ if (gtk_tree_view_column_get_visible(column)) {
+ csv.columns_order[csv.nb_cols] = gtk_tree_view_column_get_sort_column_id(column);
+ if (csv.nb_cols)
+ g_string_append(csv.CSV_str, ",");
+ g_string_append_printf(csv.CSV_str, "\"%s\"", gtk_tree_view_column_get_title(column));
+ csv.nb_cols++;
+ }
+ columns = g_list_next(columns);
+ }
+ g_list_free(list);
+
+ g_string_append(csv.CSV_str,"\n");
+ store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(csv.talkers->table)));
+ gtk_tree_model_foreach(GTK_TREE_MODEL(store), csv_handle, &csv);
+
+ /* Now that we have the CSV data, copy it into the default clipboard */
+ cb = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD); /* Get the default clipboard */
+ gtk_clipboard_set_text(cb, csv.CSV_str->str, -1); /* Copy the CSV data into the clipboard */
+ g_string_free(csv.CSV_str, TRUE); /* Free the memory */
+}
+
+static gint default_col_size[N_COLUMNS];
+
+static void
+init_default_col_size(GtkWidget *view)
+{
+
+ default_col_size[SRC_ADR_COLUMN] = get_default_col_size(view, "00000000.000000000000");
+ default_col_size[DST_ADR_COLUMN] = default_col_size[SRC_ADR_COLUMN];
+ default_col_size[SRC_PORT_COLUMN] = get_default_col_size(view, "000000");
+ default_col_size[DST_PORT_COLUMN] = default_col_size[SRC_PORT_COLUMN];
+ default_col_size[PACKETS_COLUMN] = get_default_col_size(view, "00 000 000");
+ default_col_size[BYTES_COLUMN] = get_default_col_size(view, "0 000 000 000");
+ default_col_size[PKT_AB_COLUMN] = default_col_size[PACKETS_COLUMN];
+ default_col_size[PKT_BA_COLUMN] = default_col_size[PACKETS_COLUMN];
+ default_col_size[BYTES_AB_COLUMN] = default_col_size[BYTES_COLUMN];
+ default_col_size[BYTES_BA_COLUMN] = default_col_size[BYTES_COLUMN];
+ default_col_size[START_COLUMN] = get_default_col_size(view, "000000.000000000");
+ default_col_size[DURATION_COLUMN] = get_default_col_size(view, "000000.0000");
+ default_col_size[BPS_AB_COLUMN] = get_default_col_size(view, "000000000.00");
+ default_col_size[BPS_BA_COLUMN] = default_col_size[BPS_AB_COLUMN];
+}
+
+static gboolean
+init_ct_table_page(conversations_table *conversations, GtkWidget *vbox, gboolean hide_ports, const char *table_name, const char *tap_name, const char *filter,
+ tap_packet_cb packet_func)
+{
+ int i;
+ GString *error_string;
+ char title[256];
+
+ GtkListStore *store;
+ GtkWidget *tree;
+ GtkTreeViewColumn *column;
+ GtkCellRenderer *renderer;
+ GtkTreeSortable *sortable;
+ GtkTreeSelection *sel;
+ static gboolean col_size = FALSE;
+
+ conversations->page_lb=NULL;
+ conversations->resolve_names=TRUE;
+ conversations->has_ports=!hide_ports;
+ conversations->fixed_col = FALSE;
+ conversations->default_titles[0]="Address A",
+ conversations->default_titles[1]="Port A";
+ conversations->default_titles[2]="Address B";
+ conversations->default_titles[3]="Port B";
+ conversations->default_titles[4]="Packets";
+ conversations->default_titles[5]="Bytes";
+ conversations->default_titles[6]="Packets A" UTF8_RIGHTWARDS_ARROW "B";
+ conversations->default_titles[7]="Bytes A" UTF8_RIGHTWARDS_ARROW "B";
+ conversations->default_titles[8]="Packets A" UTF8_LEFTWARDS_ARROW "B";
+ conversations->default_titles[9]="Bytes A" UTF8_LEFTWARDS_ARROW "B";
+ conversations->default_titles[10]="Rel Start";
+ conversations->default_titles[11]="Duration";
+ conversations->default_titles[12]="bps A" UTF8_RIGHTWARDS_ARROW "B";
+ conversations->default_titles[13]="bps A" UTF8_LEFTWARDS_ARROW "B";
+
+ if (strcmp(table_name, "NCP")==0) {
+ conversations->default_titles[1]="Connection A";
+ conversations->default_titles[3]="Connection B";
+ }
+
+ g_snprintf(title, sizeof(title), "%s Conversations", table_name);
+ conversations->name_lb=gtk_label_new(title);
+
+
+ /* Create the store */
+ store = gtk_list_store_new (N_COLUMNS, /* Total number of columns */
+ G_TYPE_STRING, /* Address A */
+ G_TYPE_STRING, /* Port A */
+ G_TYPE_STRING, /* Address B */
+ G_TYPE_STRING, /* Port B */
+ G_TYPE_UINT64, /* Packets */
+ G_TYPE_UINT64, /* Bytes */
+ G_TYPE_UINT64, /* Packets A->B */
+ G_TYPE_UINT64, /* Bytes A->B */
+ G_TYPE_UINT64, /* Packets A<-B */
+ G_TYPE_UINT64, /* Bytes A<-B */
+ G_TYPE_STRING, /* Start */
+ G_TYPE_STRING, /* Duration */
+ G_TYPE_STRING, /* bps A->B */
+ G_TYPE_STRING, /* bps A<-B */
+ G_TYPE_UINT); /* Index */
+
+ gtk_box_pack_start(GTK_BOX(vbox), conversations->name_lb, FALSE, FALSE, 0);
+
+ conversations->scrolled_window=scrolled_window_new(NULL, NULL);
+ gtk_box_pack_start(GTK_BOX(vbox), conversations->scrolled_window, TRUE, TRUE, 0);
+
+ tree = gtk_tree_view_new_with_model (GTK_TREE_MODEL (store));
+ conversations->table = GTK_TREE_VIEW(tree);
+ sortable = GTK_TREE_SORTABLE(store);
+
+ if (!col_size) {
+ col_size = TRUE;
+ init_default_col_size(GTK_WIDGET(conversations->table));
+ }
+
+ /* The view now holds a reference. We can get rid of our own reference */
+ g_object_unref (G_OBJECT (store));
+
+ g_object_set_data(G_OBJECT(store), CONV_PTR_KEY, conversations);
+ g_object_set_data(G_OBJECT(conversations->table), CONV_PTR_KEY, conversations);
+
+ for (i = 0; i < N_COLUMNS -1; i++) {
+ renderer = gtk_cell_renderer_text_new ();
+ g_object_set(renderer, "ypad", 0, NULL);
+ switch(i) {
+ case SRC_ADR_COLUMN: /* addresses and ports */
+ case SRC_PORT_COLUMN:
+ case DST_ADR_COLUMN:
+ case DST_PORT_COLUMN:
+ column = gtk_tree_view_column_new_with_attributes (conversations->default_titles[i], renderer, "text",
+ i, NULL);
+ if(hide_ports && (i == 1 || i == 3)){
+ /* hide srcport and dstport if we don't use ports */
+ gtk_tree_view_column_set_visible(column, FALSE);
+ }
+ gtk_tree_sortable_set_sort_func(sortable, i, ct_sort_func, GINT_TO_POINTER(i), NULL);
+ break;
+ case PACKETS_COLUMN: /* counts */
+ case BYTES_COLUMN:
+ case PKT_AB_COLUMN:
+ case BYTES_AB_COLUMN:
+ case PKT_BA_COLUMN:
+ case BYTES_BA_COLUMN:
+ g_object_set(G_OBJECT(renderer), "xalign", 1.0, NULL);
+ column = gtk_tree_view_column_new_with_attributes (conversations->default_titles[i], renderer, NULL);
+ gtk_tree_view_column_set_cell_data_func(column, renderer, u64_data_func, GINT_TO_POINTER(i), NULL);
+ break;
+ default: /* times and bps */
+ g_object_set(G_OBJECT(renderer), "xalign", 1.0, NULL);
+ column = gtk_tree_view_column_new_with_attributes (conversations->default_titles[i], renderer, "text",
+ i, NULL);
+
+ gtk_tree_sortable_set_sort_func(sortable, i, ct_sort_func, GINT_TO_POINTER(i), NULL);
+ break;
+ }
+ gtk_tree_view_column_set_sort_column_id(column, i);
+ gtk_tree_view_column_set_resizable(column, TRUE);
+ gtk_tree_view_column_set_reorderable(column, TRUE);
+ gtk_tree_view_column_set_min_width(column, 40);
+ gtk_tree_view_column_set_fixed_width(column, default_col_size[i]);
+ gtk_tree_view_append_column (conversations->table, column);
+#if 0
+ /* for capture with ten thousands conversations it's too slow */
+ if (i == PACKETS_COLUMN) {
+ gtk_tree_view_column_clicked(column);
+ gtk_tree_view_column_clicked(column);
+ }
+#endif
+ }
+ gtk_container_add(GTK_CONTAINER(conversations->scrolled_window), (GtkWidget *)conversations->table);
+ gtk_tree_view_set_rules_hint(conversations->table, TRUE);
+ gtk_tree_view_set_headers_clickable(conversations->table, TRUE);
+ gtk_tree_view_set_reorderable (conversations->table, TRUE);
+
+ conversations->num_conversations=0;
+ conversations->conversations=NULL;
+ conversations->hashtable=NULL;
+
+ sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(conversations->table));
+ gtk_tree_selection_set_mode(sel, GTK_SELECTION_SINGLE);
+
+ /* create popup menu for this table */
+ ct_create_popup_menu(conversations);
+
+ /* register the tap and rerun the taps on the packet list */
+ error_string=register_tap_listener(tap_name, conversations, filter, 0, reset_ct_table_data_cb, packet_func,
+ draw_ct_table_data_cb);
+ if(error_string){
+ simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", error_string->str);
+ g_string_free(error_string, TRUE);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+static void
+follow_stream_cb(GtkWidget *follow_stream_bt, gpointer data _U_)
+{
+ conversations_table *ct = g_object_get_data (G_OBJECT(follow_stream_bt), CONV_PTR_KEY);
+ GtkTreeIter iter;
+ GtkTreeModel *model;
+ GtkTreeSelection *sel;
+ guint32 idx = 0;
+ gchar *filter;
+ conv_t *conv;
+
+ if (!ct)
+ return;
+
+ sel = gtk_tree_view_get_selection (GTK_TREE_VIEW(ct->table));
+ if (!gtk_tree_selection_get_selected(sel, &model, &iter)) {
+ simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "No conversation selected");
+ return;
+ }
+
+ gtk_tree_model_get (model, &iter, INDEX_COLUMN, &idx, -1);
+ if (idx >= ct->num_conversations) {
+ simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "No conversation selected");
+ return;
+ }
+
+ conv = &g_array_index(ct->conversations, conv_t, idx);
+ filter = g_strdup_printf("%s==%s && %s==%s && %s==%s && %s==%s",
+ ct_get_filter_name(&conv->src_address, conv->sat, conv->port_type, FN_ANY_ADDRESS),
+ ep_address_to_str(&conv->src_address),
+ ct_get_filter_name(&conv->src_address, conv->sat, conv->port_type, FN_ANY_PORT),
+ ct_port_to_str(conv->port_type, conv->src_port),
+ ct_get_filter_name(&conv->dst_address, conv->sat, conv->port_type, FN_ANY_ADDRESS),
+ ep_address_to_str(&conv->dst_address),
+ ct_get_filter_name(&conv->dst_address, conv->sat, conv->port_type, FN_ANY_PORT),
+ ct_port_to_str(conv->port_type, conv->dst_port));
+
+ apply_selected_filter (ACTYPE_SELECTED|ACTION_MATCH, filter);
+ if (strcmp(ct->name, "TCP") == 0)
+ follow_tcp_stream_cb (follow_stream_bt, data);
+ else if (strcmp(ct->name, "UDP") == 0)
+ follow_udp_stream_cb (follow_stream_bt, data);
+ else
+ simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Unknown stream: %s", ct->name);
+
+ g_free (filter);
+}
+
+
+void
+init_conversation_table(gboolean hide_ports, const char *table_name, const char *tap_name, const char *filter, tap_packet_cb packet_func)
+{
+ conversations_table *conversations;
+ char title[256];
+ GtkWidget *vbox;
+ GtkWidget *bbox;
+ GtkWidget *close_bt, *help_bt;
+ gboolean ret;
+ GtkWidget *copy_bt, *follow_stream_bt;
+ gboolean add_follow_stream_button = FALSE;
+
+ conversations=g_malloc0(sizeof(conversations_table));
+
+ conversations->name=table_name;
+ conversations->filter=filter;
+ conversations->use_dfilter=FALSE;
+ g_snprintf(title, sizeof(title), "%s Conversations: %s", table_name, cf_get_display_name(&cfile));
+ conversations->win = dlg_window_new(title); /* transient_for top_level */
+ gtk_window_set_destroy_with_parent (GTK_WINDOW(conversations->win), TRUE);
+
+ gtk_window_set_default_size(GTK_WINDOW(conversations->win), 750, 400);
+
+ vbox=gtk_vbox_new(FALSE, 3);
+ gtk_container_add(GTK_CONTAINER(conversations->win), vbox);
+ gtk_container_set_border_width(GTK_CONTAINER(vbox), 12);
+
+ ret = init_ct_table_page(conversations, vbox, hide_ports, table_name, tap_name, filter, packet_func);
+ if(ret == FALSE) {
+ g_free(conversations);
+ return;
+ }
+
+ if ((strcmp(table_name, "TCP") == 0) || (strcmp(table_name, "UDP") == 0))
+ add_follow_stream_button = TRUE;
+
+ /* Button row. */
+ /* XXX - maybe we want to have a "Copy as CSV" stock button here? */
+ /*copy_bt = gtk_button_new_with_label ("Copy content to clipboard as CSV");*/
+ if (add_follow_stream_button)
+ bbox = dlg_button_row_new(GTK_STOCK_CLOSE, GTK_STOCK_COPY, WIRESHARK_STOCK_FOLLOW_STREAM, GTK_STOCK_HELP, NULL);
+ else
+ bbox = dlg_button_row_new(GTK_STOCK_CLOSE, GTK_STOCK_COPY, GTK_STOCK_HELP, NULL);
+ gtk_box_pack_end(GTK_BOX(vbox), bbox, FALSE, FALSE, 0);
+
+ close_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_CLOSE);
+ window_set_cancel_button(conversations->win, close_bt, window_cancel_button_cb);
+
+ copy_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_COPY);
+ gtk_widget_set_tooltip_text(copy_bt, "Copy all statistical values of this page to the clipboard in CSV (Comma Separated Values) format.");
+ g_object_set_data(G_OBJECT(copy_bt), CONV_PTR_KEY, conversations);
+ g_signal_connect(copy_bt, "clicked", G_CALLBACK(copy_as_csv_cb), NULL);
+
+ if (add_follow_stream_button) {
+ follow_stream_bt = g_object_get_data(G_OBJECT(bbox), WIRESHARK_STOCK_FOLLOW_STREAM);
+ g_object_set_data(G_OBJECT(follow_stream_bt), E_DFILTER_TE_KEY, main_display_filter_widget);
+ g_object_set_data(G_OBJECT(follow_stream_bt), CONV_PTR_KEY, conversations);
+ g_signal_connect(follow_stream_bt, "clicked", G_CALLBACK(follow_stream_cb), NULL);
+ }
+
+ help_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_HELP);
+ g_signal_connect(help_bt, "clicked", G_CALLBACK(topic_cb), (gpointer)HELP_STATS_CONVERSATIONS_DIALOG);
+
+ g_signal_connect(conversations->win, "delete_event", G_CALLBACK(window_delete_event_cb), NULL);
+ g_signal_connect(conversations->win, "destroy", G_CALLBACK(ct_win_destroy_cb), conversations);
+
+ gtk_widget_show_all(conversations->win);
+ window_present(conversations->win);
+
+ cf_retap_packets(&cfile);
+ gdk_window_raise(gtk_widget_get_window(conversations->win));
+}
+
+
+
+static void
+ct_nb_switch_page_cb(GtkNotebook *nb, gpointer *pg _U_, guint page, gpointer data)
+{
+ GtkWidget *copy_bt = (GtkWidget *) data;
+ GtkWidget *follow_stream_bt = g_object_get_data(G_OBJECT(nb), FOLLOW_STREAM_BT_KEY);
+ void **pages = g_object_get_data(G_OBJECT(nb), NB_PAGES_KEY);
+
+ page++;
+
+ if (pages && page > 0 && (int) page <= GPOINTER_TO_INT(pages[0]) && copy_bt) {
+ g_object_set_data(G_OBJECT(copy_bt), CONV_PTR_KEY, pages[page]);
+ g_object_set_data(G_OBJECT(follow_stream_bt), CONV_PTR_KEY, pages[page]);
+ }
+
+ /* Filter Stream only available for TCP and UDP */
+ if (strcmp(((conversations_table *)pages[page])->name, "TCP") == 0) {
+ gtk_widget_set_tooltip_text(follow_stream_bt, "Follow TCP Stream.");
+ gtk_widget_set_sensitive(follow_stream_bt, TRUE);
+ } else if (strcmp(((conversations_table *)pages[page])->name, "UDP") == 0) {
+ gtk_widget_set_tooltip_text(follow_stream_bt, "Follow UDP Stream.");
+ gtk_widget_set_sensitive(follow_stream_bt, TRUE);
+ } else {
+ gtk_widget_set_tooltip_text(follow_stream_bt, "Follow TCP or UDP Stream.");
+ gtk_widget_set_sensitive(follow_stream_bt, FALSE);
+ }
+}
+
+static void
+ct_win_destroy_notebook_cb(GtkWindow *win _U_, gpointer data)
+{
+ void ** pages = data;
+ int page;
+
+ /* first "page" contains the number of pages */
+ for (page=1; page<=GPOINTER_TO_INT(pages[0]); page++) {
+ ct_win_destroy_cb(NULL, pages[page]);
+ }
+ g_free(pages);
+}
+
+static conversations_table *
+init_ct_notebook_page_cb(gboolean hide_ports, const char *table_name, const char *tap_name, const char *filter, tap_packet_cb packet_func)
+{
+ gboolean ret;
+ GtkWidget *page_vbox;
+ conversations_table *conversations;
+
+ conversations=g_malloc0(sizeof(conversations_table));
+ conversations->name=table_name;
+ conversations->filter=filter;
+ conversations->resolve_names=TRUE;
+ conversations->use_dfilter=FALSE;
+
+ page_vbox=gtk_vbox_new(FALSE, 6);
+ conversations->win = page_vbox;
+ gtk_container_set_border_width(GTK_CONTAINER(page_vbox), 6);
+
+ ret = init_ct_table_page(conversations, page_vbox, hide_ports, table_name, tap_name, filter, packet_func);
+ if(ret == FALSE) {
+ g_free(conversations);
+ return NULL;
+ }
+
+ return conversations;
+}
+
+
+typedef struct {
+ gboolean hide_ports; /* hide TCP / UDP port columns */
+ const char *table_name; /* GUI output name */
+ const char *tap_name; /* internal name */
+ const char *filter; /* display filter string (unused) */
+ tap_packet_cb packet_func; /* function to be called for new incoming packets */
+} register_ct_t;
+
+
+static GSList *registered_ct_tables = NULL;
+
+void
+register_conversation_table(gboolean hide_ports, const char *table_name, const char *tap_name, const char *filter, tap_packet_cb packet_func)
+{
+ register_ct_t *table;
+
+ table = g_malloc(sizeof(register_ct_t));
+
+ table->hide_ports = hide_ports;
+ table->table_name = table_name;
+ table->tap_name = tap_name;
+ table->filter = filter;
+ table->packet_func = packet_func;
+
+ registered_ct_tables = g_slist_append(registered_ct_tables, table);
+}
+
+
+static void
+ct_resolve_toggle_dest(GtkWidget *widget, gpointer data)
+{
+ int page;
+ void ** pages = data;
+ gboolean resolve_names;
+ conversations_table *conversations;
+
+
+ resolve_names = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (widget));
+
+ for (page=1; page<=GPOINTER_TO_INT(pages[0]); page++) {
+ conversations = pages[page];
+ conversations->resolve_names = resolve_names;
+
+ draw_ct_table_addresses(conversations);
+
+ }
+}
+
+
+static void
+ct_filter_toggle_dest(GtkWidget *widget, gpointer data)
+{
+ int page;
+ void ** pages = data;
+ gboolean use_filter;
+ conversations_table *conversations = NULL;
+
+ use_filter = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (widget));
+
+ for (page=1; page<=GPOINTER_TO_INT(pages[0]); page++) {
+ conversations = pages[page];
+ conversations->use_dfilter = use_filter;
+ reset_ct_table_data(conversations);
+ }
+
+ cf_retap_packets(&cfile);
+ if (conversations) {
+ gdk_window_raise(gtk_widget_get_window(conversations->win));
+ }
+}
+
+
+void
+init_conversation_notebook_cb(GtkWidget *w _U_, gpointer d _U_)
+{
+ conversations_table *conversations;
+ char title[256];
+ GtkWidget *vbox;
+ GtkWidget *hbox;
+ GtkWidget *bbox;
+ GtkWidget *close_bt, *help_bt;
+ GtkWidget *win;
+ GtkWidget *resolv_cb;
+ GtkWidget *filter_cb;
+ int page;
+ void ** pages;
+ GtkWidget *nb;
+ GtkWidget *page_lb;
+ GSList *current_table;
+ register_ct_t *registered;
+ GtkWidget *copy_bt;
+ GtkWidget *follow_stream_bt;
+
+ pages = g_malloc(sizeof(void *) * (g_slist_length(registered_ct_tables) + 1));
+
+ g_snprintf(title, sizeof(title), "Conversations: %s", cf_get_display_name(&cfile));
+ win = dlg_window_new(title); /* transient_for top_level */
+ gtk_window_set_destroy_with_parent (GTK_WINDOW(win), TRUE);
+
+ gtk_window_set_default_size(GTK_WINDOW(win), 750, 400);
+
+ vbox=gtk_vbox_new(FALSE, 6);
+ gtk_container_add(GTK_CONTAINER(win), vbox);
+ gtk_container_set_border_width(GTK_CONTAINER(vbox), 12);
+
+ nb = gtk_notebook_new();
+ gtk_container_add(GTK_CONTAINER(vbox), nb);
+ g_object_set_data(G_OBJECT(nb), NB_PAGES_KEY, pages);
+
+ page = 0;
+
+ current_table = registered_ct_tables;
+ while(current_table) {
+ registered = current_table->data;
+ page_lb = gtk_label_new("");
+ conversations = init_ct_notebook_page_cb(registered->hide_ports, registered->table_name, registered->tap_name,
+ registered->filter, registered->packet_func);
+ g_object_set_data(G_OBJECT(conversations->win), CONV_PTR_KEY, conversations);
+ gtk_notebook_append_page(GTK_NOTEBOOK(nb), conversations->win, page_lb);
+ conversations->win = win;
+ conversations->page_lb = page_lb;
+ pages[++page] = conversations;
+
+ current_table = g_slist_next(current_table);
+ }
+
+ pages[0] = GINT_TO_POINTER(page);
+
+ hbox = gtk_hbox_new(FALSE, 3);
+ gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
+
+ resolv_cb = gtk_check_button_new_with_mnemonic("Name resolution");
+ gtk_container_add(GTK_CONTAINER(hbox), resolv_cb);
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(resolv_cb), TRUE);
+ gtk_widget_set_tooltip_text(resolv_cb, "Show results of name resolutions rather than the \"raw\" values. "
+ "Please note: The corresponding name resolution must be enabled.");
+ g_signal_connect(resolv_cb, "toggled", G_CALLBACK(ct_resolve_toggle_dest), pages);
+
+ filter_cb = gtk_check_button_new_with_mnemonic("Limit to display filter");
+ gtk_container_add(GTK_CONTAINER(hbox), filter_cb);
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(filter_cb), FALSE);
+ gtk_widget_set_tooltip_text(filter_cb, "Limit the list to conversations matching the current display filter.");
+ g_signal_connect(filter_cb, "toggled", G_CALLBACK(ct_filter_toggle_dest), pages);
+
+ /* Button row. */
+ /* XXX - maybe we want to have a "Copy as CSV" stock button here? */
+ /*copy_bt = gtk_button_new_with_label ("Copy content to clipboard as CSV");*/
+ bbox = dlg_button_row_new(GTK_STOCK_CLOSE, GTK_STOCK_COPY, WIRESHARK_STOCK_FOLLOW_STREAM, GTK_STOCK_HELP, NULL);
+
+ gtk_box_pack_end(GTK_BOX(vbox), bbox, FALSE, FALSE, 0);
+
+ close_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_CLOSE);
+ window_set_cancel_button(win, close_bt, window_cancel_button_cb);
+
+ copy_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_COPY);
+ gtk_widget_set_tooltip_text(copy_bt, "Copy all statistical values of this page to the clipboard in CSV (Comma Separated Values) format.");
+ g_signal_connect(copy_bt, "clicked", G_CALLBACK(copy_as_csv_cb), NULL);
+ g_object_set_data(G_OBJECT(copy_bt), CONV_PTR_KEY, pages[page]);
+
+ follow_stream_bt = g_object_get_data(G_OBJECT(bbox), WIRESHARK_STOCK_FOLLOW_STREAM);
+ gtk_widget_set_tooltip_text(follow_stream_bt, "Follow Stream.");
+ g_object_set_data(G_OBJECT(follow_stream_bt), E_DFILTER_TE_KEY, main_display_filter_widget);
+ g_object_set_data(G_OBJECT(follow_stream_bt), CONV_PTR_KEY, pages[page]);
+ g_signal_connect(follow_stream_bt, "clicked", G_CALLBACK(follow_stream_cb), NULL);
+
+ g_object_set_data(G_OBJECT(nb), FOLLOW_STREAM_BT_KEY, follow_stream_bt);
+ g_signal_connect(nb, "switch-page", G_CALLBACK(ct_nb_switch_page_cb), copy_bt);
+
+ help_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_HELP);
+ g_signal_connect(help_bt, "clicked", G_CALLBACK(topic_cb), (gpointer)HELP_STATS_CONVERSATIONS_DIALOG);
+
+ g_signal_connect(win, "delete_event", G_CALLBACK(window_delete_event_cb), NULL);
+ g_signal_connect(win, "destroy", G_CALLBACK(ct_win_destroy_notebook_cb), pages);
+
+ gtk_widget_show_all(win);
+ window_present(win);
+
+ cf_retap_packets(&cfile);
+ gdk_window_raise(gtk_widget_get_window(win));
+}
+
+typedef struct _key {
+ address addr1;
+ address addr2;
+ guint32 port1;
+ guint32 port2;
+} conv_key_t;
+
+
+/*
+ * Compute the hash value for two given address/port pairs if the match
+ * is to be exact.
+ */
+static guint
+conversation_hash(gconstpointer v)
+{
+ const conv_key_t *key = (const conv_key_t *)v;
+ guint hash_val;
+
+ hash_val = 0;
+ ADD_ADDRESS_TO_HASH(hash_val, &key->addr1);
+ hash_val += key->port1;
+ ADD_ADDRESS_TO_HASH(hash_val, &key->addr2);
+ hash_val += key->port2;
+
+ return hash_val;
+}
+
+/*
+ * Compare two conversation keys for an exact match.
+ */
+static gint
+conversation_match(gconstpointer v, gconstpointer w)
+{
+ const conv_key_t *v1 = (const conv_key_t *)v;
+ const conv_key_t *v2 = (const conv_key_t *)w;
+
+ if (v1->port1 == v2->port1 &&
+ v1->port2 == v2->port2 &&
+ ADDRESSES_EQUAL(&v1->addr1, &v2->addr1) &&
+ ADDRESSES_EQUAL(&v1->addr2, &v2->addr2)) {
+ return 1;
+ }
+
+ if (v1->port2 == v2->port1 &&
+ v1->port1 == v2->port2 &&
+ ADDRESSES_EQUAL(&v1->addr2, &v2->addr1) &&
+ ADDRESSES_EQUAL(&v1->addr1, &v2->addr2)) {
+ return 1;
+ }
+
+ /*
+ * The addresses or the ports don't match.
+ */
+ return 0;
+}
+
+
+void
+add_conversation_table_data(conversations_table *ct, const address *src, const address *dst, guint32 src_port, guint32 dst_port, int num_frames, int num_bytes, nstime_t *ts, SAT_E sat, int port_type_val)
+{
+ const address *addr1, *addr2;
+ guint32 port1, port2;
+ conv_t *conversation=NULL;
+ unsigned int conversation_idx=0;
+
+ if(src_port>dst_port){
+ addr1=src;
+ addr2=dst;
+ port1=src_port;
+ port2=dst_port;
+ } else if(src_port<dst_port){
+ addr2=src;
+ addr1=dst;
+ port2=src_port;
+ port1=dst_port;
+ } else if(CMP_ADDRESS(src, dst)<0){
+ addr1=src;
+ addr2=dst;
+ port1=src_port;
+ port2=dst_port;
+ } else {
+ addr2=src;
+ addr1=dst;
+ port2=src_port;
+ port1=dst_port;
+ }
+
+ /* if we dont have any entries at all yet */
+ if(ct->conversations==NULL){
+ ct->conversations= g_array_sized_new(FALSE, FALSE, sizeof(conv_t), 10000);
+
+ ct->hashtable = g_hash_table_new_full(conversation_hash,
+ conversation_match, /* key_equal_func */
+ g_free, /* key_destroy_func */
+ NULL); /* value_destroy_func */
+
+ }
+ else {
+ /* try to find it among the existing known conversations */
+ conv_key_t existing_key;
+
+ existing_key.addr1 = *addr1;
+ existing_key.addr2 = *addr2;
+ existing_key.port1 = port1;
+ existing_key.port2 = port2;
+ conversation_idx = GPOINTER_TO_UINT(g_hash_table_lookup(ct->hashtable, &existing_key));
+ if (conversation_idx) {
+ conversation_idx--;
+ conversation=&g_array_index(ct->conversations, conv_t, conversation_idx);
+ }
+ }
+
+ /* if we still dont know what conversation this is it has to be a new one
+ and we have to allocate it and append it to the end of the list */
+ if(conversation==NULL){
+ conv_key_t *new_key;
+ conv_t conv;
+
+ COPY_ADDRESS(&conv.src_address, addr1);
+ COPY_ADDRESS(&conv.dst_address, addr2);
+ conv.sat=sat;
+ conv.port_type=port_type_val;
+ conv.src_port=port1;
+ conv.dst_port=port2;
+ conv.rx_frames=0;
+ conv.tx_frames=0;
+ conv.rx_bytes=0;
+ conv.tx_bytes=0;
+ conv.iter_valid = FALSE;
+ conv.modified = TRUE;
+
+ if (ts) {
+ memcpy(&conv.start_time, ts, sizeof(conv.start_time));
+ memcpy(&conv.stop_time, ts, sizeof(conv.stop_time));
+ } else {
+ nstime_set_unset(&conv.start_time);
+ nstime_set_unset(&conv.stop_time);
+ }
+ g_array_append_val(ct->conversations, conv);
+ conversation_idx=ct->num_conversations;
+ conversation=&g_array_index(ct->conversations, conv_t, conversation_idx);
+
+ /* ct->conversations address is not a constant but src/dst_address.data are */
+ new_key = g_new(conv_key_t, 1);
+ SET_ADDRESS(&new_key->addr1, conversation->src_address.type, conversation->src_address.len, conversation->src_address.data);
+ SET_ADDRESS(&new_key->addr2, conversation->dst_address.type, conversation->dst_address.len, conversation->dst_address.data);
+ new_key->port1 = port1;
+ new_key->port2 = port2;
+ g_hash_table_insert(ct->hashtable, new_key, GUINT_TO_POINTER(conversation_idx +1));
+
+ ct->num_conversations++;
+ }
+
+ /* update the conversation struct */
+ conversation->modified = TRUE;
+ if( (!CMP_ADDRESS(src, addr1))&&(!CMP_ADDRESS(dst, addr2))&&(src_port==port1)&&(dst_port==port2) ){
+ conversation->tx_frames+=num_frames;
+ conversation->tx_bytes+=num_bytes;
+ } else {
+ conversation->rx_frames+=num_frames;
+ conversation->rx_bytes+=num_bytes;
+ }
+
+ if (ts) {
+ if (nstime_cmp(ts, &conversation->stop_time) > 0) {
+ memcpy(&conversation->stop_time, ts, sizeof(conversation->stop_time));
+ } else if (nstime_cmp(ts, &conversation->start_time) < 0) {
+ memcpy(&conversation->start_time, ts, sizeof(conversation->start_time));
+ }
+ }
+}
+
+/*
+ * Editor modelines
+ *
+ * Local Variables:
+ * c-basic-offset: 4
+ * tab-width: 8
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * ex: set shiftwidth=4 tabstop=8 expandtab:
+ * :indentSize=4:tabSize=8:noTabs=true:
+ */