Add Compile BPF to the capture options dialog description.
[obnox/wireshark/wip.git] / gtk / wlan_stat_dlg.c
1 /* wlan_stat_dlg.c
2  * Copyright 2008 Stig Bjorlykke <stig@bjorlykke.org>
3  *
4  * $Id$
5  *
6  * Wireshark - Network traffic analyzer
7  * By Gerald Combs <gerald@wireshark.org>
8  * Copyright 1998 Gerald Combs
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License
12  * as published by the Free Software Foundation; either version 2
13  * of the License, or (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
23  */
24
25
26 #ifdef HAVE_CONFIG_H
27 #include "config.h"
28 #endif
29
30 #ifdef HAVE_SYS_TYPES_H
31 #include <sys/types.h>
32 #endif
33 #include <string.h>
34
35 #include <gtk/gtk.h>
36
37 #include <epan/packet.h>
38 #include <epan/addr_resolv.h>
39 #include <epan/tap.h>
40 #include <epan/dissectors/packet-ieee80211.h>
41 #include <epan/strutil.h>
42
43 #include "../simple_dialog.h"
44 #include "../stat_menu.h"
45
46 #include "gtk/gtkglobals.h"
47 #include "gtk/dlg_utils.h"
48 #include "gtk/filter_utils.h"
49 #include "gtk/gui_stat_menu.h"
50 #include "gtk/gui_utils.h"
51 #include "gtk/recent.h"
52 #include "gtk/help_dlg.h"
53 #include "gtk/main.h"
54 #include "gtk/utf8_entities.h"
55
56 enum {
57         BSSID_COLUMN,
58         CHANNEL_COLUMN,
59         SSID_COLUMN,
60         PERCENT_COLUMN,
61         BEACONS_COLUMN,
62         DATA_COLUMN,
63         PROBE_REQ_COLUMN,
64         PROBE_RESP_COLUMN,
65         AUTH_COLUMN,
66         DEAUTH_COLUMN,
67         OTHER_COLUMN,
68         PROTECTION_COLUMN,
69         PERCENT_VALUE_COLUMN,
70         TABLE_COLUMN,
71         NUM_COLUMNS
72 };
73
74 static const gchar *titles[] = { "BSSID", "Ch.", "SSID", "% Packets", "Beacons", "Data Packets",
75                                  "Probe Req", "Probe Resp", "Auth", "Deauth", "Other", "Protection" };
76
77 enum {
78         ADDRESS_COLUMN,
79         PERCENT_2_COLUMN,
80         DATA_SENT_COLUMN,
81         DATA_REC_COLUMN,
82         PROBE_REQ_2_COLUMN,
83         PROBE_RESP_2_COLUMN,
84         AUTH_2_COLUMN,
85         DEAUTH_2_COLUMN,
86         OTHER_2_COLUMN,
87         COMMENT_COLUMN,
88         PERCENT_VALUE_2_COLUMN,
89         DETAILS_COLUMN,
90         NUM_DETAIL_COLUMNS
91 };
92
93 static const gchar *detail_titles[] = { "Address", "% Packets", "Data Sent", "Data Received",
94                                         "Probe Req", "Probe Resp", "Auth", "Deauth", "Other", "Comment" };
95
96 typedef struct wlan_details_ep {
97         struct wlan_details_ep *next;
98         address addr;
99         guint32 probe_req;
100         guint32 probe_rsp;
101         guint32 auth;
102         guint32 deauth;
103         guint32 data_sent;
104         guint32 data_received;
105         guint32 other;
106         guint32 number_of_packets;
107         GtkTreeIter iter;
108         gboolean iter_valid;
109 } wlan_details_ep_t;
110
111 typedef struct wlan_ep {
112         struct wlan_ep* next;
113         address bssid;
114         struct _wlan_stats stats;
115         guint32 type[256];
116         guint32 number_of_packets;
117         GtkTreeIter iter;
118         gboolean iter_valid;
119         gboolean probe_req_searched;
120         gboolean is_broadcast;
121         struct wlan_details_ep *details;
122 } wlan_ep_t;
123
124 static GtkWidget  *wlanstat_dlg_w = NULL;
125 static GtkWidget  *wlanstat_pane = NULL;
126 static GtkWidget  *wlanstat_name_lb = NULL;
127 static address    broadcast;
128
129 /* used to keep track of the statistics for an entire program interface */
130 typedef struct _wlan_stat_t {
131         GtkTreeView  *table;
132         GtkTreeView  *details;
133         GtkWidget  *menu;
134         GtkWidget  *details_menu;
135         guint32    number_of_packets;
136         guint32    num_entries;
137         guint32    num_details;
138         gboolean   resolve_names;
139         gboolean   use_dfilter;
140         gboolean   show_only_existing;
141         wlan_ep_t* ep_list;
142 } wlanstat_t;
143
144 static void
145 dealloc_wlan_details_ep (wlan_details_ep_t *details)
146 {
147         wlan_details_ep_t *tmp;
148
149         while (details) {
150                 tmp = details;
151                 details = details->next;
152                 g_free (tmp);
153         }
154 }
155
156 static void
157 wlanstat_reset (void *phs)
158 {
159         wlanstat_t* wlan_stat = (wlanstat_t *)phs;
160         wlan_ep_t* list = wlan_stat->ep_list;
161         wlan_ep_t* tmp = NULL;
162         char title[256];
163         GString *error_string;
164         GtkListStore *store;
165         const char *filter = NULL;
166
167         if (wlanstat_dlg_w != NULL) {
168             g_snprintf (title, sizeof(title), "Wireshark: WLAN Traffic Statistics: %s",
169                             cf_get_display_name(&cfile));
170                 gtk_window_set_title(GTK_WINDOW(wlanstat_dlg_w), title);
171         }
172
173         if (wlan_stat->use_dfilter) {
174                 filter = gtk_entry_get_text(GTK_ENTRY(main_display_filter_widget));
175         }
176
177         error_string = set_tap_dfilter (wlan_stat, filter);
178         if (error_string) {
179                 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", error_string->str);
180                 g_string_free(error_string, TRUE);
181                 return;
182         }
183
184         if (wlan_stat->use_dfilter) {
185                 if (filter && strlen(filter)) {
186                     g_snprintf(title, sizeof(title), "Network Overview - Filter: %s", filter);
187                 } else {
188                     g_snprintf(title, sizeof(title), "Network Overview - No Filter");
189                 }
190         } else {
191                 g_snprintf(title, sizeof(title), "Network Overview");
192         }
193         gtk_frame_set_label(GTK_FRAME(wlanstat_name_lb), title);
194
195         /* remove all entries from the list */
196         store = GTK_LIST_STORE(gtk_tree_view_get_model(wlan_stat->table));
197         gtk_list_store_clear(store);
198         store = GTK_LIST_STORE(gtk_tree_view_get_model(wlan_stat->details));
199         gtk_list_store_clear(store);
200
201         if (!list)
202                 return;
203
204         while (list) {
205                 tmp = list;
206                 dealloc_wlan_details_ep (tmp->details);
207                 list = tmp->next;
208                 g_free (tmp);
209         }
210
211         wlan_stat->ep_list = NULL;
212         wlan_stat->number_of_packets = 0;
213 }
214
215 static void
216 invalidate_detail_iters (wlanstat_t *hs)
217 {
218         wlan_ep_t *ep = hs->ep_list;
219         wlan_details_ep_t *d_ep;
220
221         while (ep) {
222                 d_ep = ep->details;
223                 while (d_ep) {
224                         d_ep->iter_valid = FALSE;
225                         d_ep = d_ep->next;
226                 }
227                 ep = ep->next;
228         }
229 }
230
231 static wlan_ep_t*
232 alloc_wlan_ep (struct _wlan_hdr *si, packet_info *pinfo _U_)
233 {
234         wlan_ep_t* ep;
235
236         if (!si)
237                 return NULL;
238
239         ep = g_malloc (sizeof(wlan_ep_t));
240
241         SE_COPY_ADDRESS (&ep->bssid, &si->bssid);
242         ep->stats.channel = si->stats.channel;
243         memcpy (ep->stats.ssid, si->stats.ssid, MAX_SSID_LEN);
244         ep->stats.ssid_len = si->stats.ssid_len;
245         g_strlcpy (ep->stats.protection, si->stats.protection, MAX_PROTECT_LEN);
246         memset(&ep->type, 0, sizeof (int) * 256);
247         ep->number_of_packets = 0;
248         ep->details = NULL;
249         ep->iter_valid = FALSE;
250         ep->probe_req_searched = FALSE;
251         ep->is_broadcast = FALSE;
252         ep->next = NULL;
253
254         return ep;
255 }
256
257 static wlan_details_ep_t*
258 alloc_wlan_details_ep (address *addr)
259 {
260         wlan_details_ep_t* d_ep;
261
262         if (!addr)
263                 return NULL;
264
265         if (!(d_ep = g_malloc (sizeof(wlan_details_ep_t))))
266                 return NULL;
267
268         SE_COPY_ADDRESS (&d_ep->addr, addr);
269         d_ep->probe_req = 0;
270         d_ep->probe_rsp = 0;
271         d_ep->auth = 0;
272         d_ep->deauth = 0;
273         d_ep->data_sent = 0;
274         d_ep->data_received = 0;
275         d_ep->other = 0;
276         d_ep->number_of_packets = 0;
277         d_ep->iter_valid = FALSE;
278         d_ep->next = NULL;
279
280         return d_ep;
281 }
282
283 static wlan_details_ep_t *
284 get_details_ep (wlan_ep_t *te, address *addr)
285 {
286         wlan_details_ep_t *tmp, *d_te = NULL;
287
288         if (!te->details) {
289                 te->details = alloc_wlan_details_ep (addr);
290                 d_te = te->details;
291         } else {
292                 for (tmp = te->details; tmp; tmp = tmp->next) {
293                         if (!CMP_ADDRESS (&tmp->addr, addr)) {
294                                 d_te = tmp;
295                                 break;
296                         }
297                 }
298
299                 if (!d_te) {
300                         if ((d_te = alloc_wlan_details_ep (addr)) != NULL) {
301                                 d_te->next = te->details;
302                                 te->details = d_te;
303                         }
304                 }
305         }
306
307         g_assert (d_te != NULL);
308
309         return d_te;
310 }
311
312 static void
313 wlanstat_packet_details (wlan_ep_t *te, guint32 type, address *addr, gboolean src)
314 {
315         wlan_details_ep_t *d_te = get_details_ep (te, addr);
316
317         switch (type) {
318         case 0x04:
319                 d_te->probe_req++;
320                 break;
321         case 0x05:
322                 d_te->probe_rsp++;
323                 break;
324         case 0x08:
325                 /* No counting for beacons */
326                 break;
327         case 0x0B:
328                 d_te->auth++;
329                 break;
330         case 0x0C:
331                 d_te->deauth++;
332                 break;
333         case 0x20:
334         case 0x21:
335         case 0x22:
336         case 0x23:
337         case 0x28:
338         case 0x29:
339         case 0x2A:
340         case 0x2B:
341                 if (src) {
342                         d_te->data_sent++;
343                 } else {
344                         d_te->data_received++;
345                 }
346                 break;
347         default:
348                 d_te->other++;
349                 break;
350         }
351
352         if (type != 0x08) {
353                 /* Do not count beacons in details */
354                 d_te->number_of_packets++;
355         }
356 }
357
358 static gboolean
359 is_broadcast(address *addr)
360 {
361 #if 0
362         /* doesn't work if MAC resolution is disable */
363         return strcmp(get_addr_name(addr), "Broadcast") == 0;
364 #endif
365         return ADDRESSES_EQUAL(&broadcast, addr);
366 }
367
368 static gboolean
369 ssid_equal(struct _wlan_stats *st1, struct _wlan_stats *st2 )
370 {
371         return st1->ssid_len == st2->ssid_len && memcmp (st1->ssid, st2->ssid, st1->ssid_len) == 0;
372 }
373
374 static int
375 wlanstat_packet (void *phs, packet_info *pinfo, epan_dissect_t *edt _U_, const void *phi)
376 {
377
378         wlanstat_t *hs = (wlanstat_t *)phs;
379         wlan_ep_t *tmp = NULL, *te = NULL;
380         struct _wlan_hdr *si = (struct _wlan_hdr *) phi;
381
382         if (!hs)
383                 return (0);
384
385         hs->number_of_packets++;
386         if (!hs->ep_list) {
387                 hs->ep_list = alloc_wlan_ep (si, pinfo);
388                 te = hs->ep_list;
389                 te->is_broadcast = is_broadcast(&si->bssid);
390         } else {
391                 for (tmp = hs->ep_list; tmp; tmp = tmp->next) {
392                         if (((si->type == 0x04 && (
393                               (tmp->stats.ssid_len == 0 && si->stats.ssid_len == 0 && tmp->is_broadcast)
394                               || (si->stats.ssid_len != 0 && ssid_equal(&tmp->stats, &si->stats))
395                              )))
396                             ||
397                             (si->type != 0x04 && !CMP_ADDRESS (&tmp->bssid, &si->bssid))) {
398                                 te = tmp;
399                                 break;
400                         }
401                 }
402
403                 if (!te) {
404                         te = alloc_wlan_ep (si, pinfo);
405                         te->is_broadcast = is_broadcast(&si->bssid);
406                         te->next = hs->ep_list;
407                         hs->ep_list = te;
408                 }
409
410                 if (!te->probe_req_searched && (si->type != 0x04) && (te->type[0x04] == 0) &&
411                     (si->stats.ssid_len > 1 || si->stats.ssid[0] != 0)) {
412                         /*
413                          * We have found a matching entry without Probe Requests.
414                          * Search the rest of the entries for a corresponding entry
415                          * matching the SSID and BSSID == Broadcast.
416                          *
417                          * This is because we can have a hidden SSID or Probe Request
418                          * before we have a Beacon, Association Request, etc.
419                          */
420                         wlan_ep_t *prev = NULL;
421                         GtkListStore *store = GTK_LIST_STORE(gtk_tree_view_get_model(hs->table));
422                         te->probe_req_searched = TRUE;
423                         for (tmp = hs->ep_list; tmp; tmp = tmp->next) {
424                                 if (tmp != te && tmp->is_broadcast && ssid_equal (&si->stats, &tmp->stats)) {
425                                         /*
426                                          * Found a matching entry. Merge with the previous
427                                          * found entry and remove from list.
428                                          */
429                                         te->type[0x04] += tmp->type[0x04];
430                                         te->number_of_packets += tmp->number_of_packets;
431
432                                         if (tmp->details && tmp->details->next) {
433                                                 /* Adjust received probe requests */
434                                                 wlan_details_ep_t *d_te;
435                                                 d_te = get_details_ep (te, &tmp->details->addr);
436                                                 d_te->probe_req += tmp->type[0x04];
437                                                 d_te->number_of_packets += tmp->type[0x04];
438                                                 d_te = get_details_ep (te, &tmp->details->next->addr);
439                                                 d_te->probe_req += tmp->type[0x04];
440                                                 d_te->number_of_packets += tmp->type[0x04];
441                                         }
442                                         if (prev) {
443                                                 prev->next = tmp->next;
444                                         } else {
445                                                 hs->ep_list = tmp->next;
446                                         }
447                                         dealloc_wlan_details_ep (tmp->details);
448                                         if (tmp->iter_valid) {
449                                                 gtk_list_store_remove(store, &tmp->iter);
450                                         }
451                                         g_free (tmp);
452                                         break;
453                                 }
454                                 prev = tmp;
455                         }
456                 }
457         }
458
459         if(!te)
460                 return (0);
461
462         if (te->stats.channel == 0 && si->stats.channel != 0) {
463                 te->stats.channel = si->stats.channel;
464         }
465         if (te->stats.ssid[0] == 0 && si->stats.ssid_len != 0) {
466                 memcpy (te->stats.ssid, si->stats.ssid, MAX_SSID_LEN);
467                 te->stats.ssid_len = si->stats.ssid_len;
468         }
469         if (te->stats.protection[0] == 0 && si->stats.protection[0] != 0) {
470                 g_strlcpy (te->stats.protection, si->stats.protection, MAX_PROTECT_LEN);
471         }
472         te->type[si->type]++;
473         te->number_of_packets++;
474
475         wlanstat_packet_details (te, si->type, &si->src, TRUE);  /* Register source */
476         wlanstat_packet_details (te, si->type, &si->dst, FALSE); /* Register destination */
477
478         return (1);
479 }
480
481 static void
482 wlanstat_draw_details(wlanstat_t *hs, wlan_ep_t *wlan_ep, gboolean clear)
483 {
484         wlan_details_ep_t *tmp = NULL;
485         char addr[256], comment[256], percent[256];
486         gboolean broadcast_flag, basestation_flag;
487         float f;
488         GtkListStore *store;
489
490         store = GTK_LIST_STORE(gtk_tree_view_get_model(hs->details));
491         if (clear) {
492                 gtk_list_store_clear(store);
493                 invalidate_detail_iters(hs);
494         }
495         hs->num_details = 0;
496
497         for(tmp = wlan_ep->details; tmp; tmp=tmp->next) {
498                 broadcast_flag = is_broadcast(&tmp->addr);
499                 basestation_flag = !broadcast_flag && !CMP_ADDRESS(&tmp->addr, &wlan_ep->bssid);
500
501                 if ((wlan_ep->number_of_packets - wlan_ep->type[0x08]) > 0) {
502                         f = (float)(((float)tmp->number_of_packets * 100.0) / (wlan_ep->number_of_packets - wlan_ep->type[0x08]));
503                 } else {
504                         f = 0.0f;
505                 }
506
507                 if (hs->resolve_names) {
508                         g_strlcpy (addr, get_addr_name(&tmp->addr), sizeof(addr));
509                 } else {
510                         g_strlcpy (addr, ep_address_to_str(&tmp->addr), sizeof(addr));
511                 }
512                 if (basestation_flag) {
513                         g_strlcpy (comment, "Base station", sizeof(comment));
514                 } else {
515                         g_strlcpy (comment, " ", sizeof(comment));
516                 }
517                 g_snprintf (percent, sizeof(percent), "%.2f %%", f);
518
519                 if (!tmp->iter_valid) {
520                         gtk_list_store_append(store, &tmp->iter);
521                         tmp->iter_valid = TRUE;
522                 }
523                 gtk_list_store_set(store, &tmp->iter,
524                                    ADDRESS_COLUMN, addr,
525                                    PERCENT_2_COLUMN, percent,
526                                    DATA_SENT_COLUMN, tmp->data_sent,
527                                    DATA_REC_COLUMN, tmp->data_received,
528                                    PROBE_REQ_2_COLUMN, tmp->probe_req,
529                                    PROBE_RESP_2_COLUMN, tmp->probe_rsp,
530                                    AUTH_2_COLUMN, tmp->auth,
531                                    DEAUTH_2_COLUMN, tmp->deauth,
532                                    OTHER_2_COLUMN, tmp->other,
533                                    COMMENT_COLUMN, comment,
534                                    PERCENT_VALUE_2_COLUMN, f,
535                                    DETAILS_COLUMN, tmp,
536                                    -1);
537
538                 hs->num_details++;
539         }
540 }
541
542 static void
543 wlanstat_draw(void *phs)
544 {
545         wlanstat_t *hs = (wlanstat_t *)phs;
546         wlan_ep_t* list = hs->ep_list, *tmp = 0;
547         guint32 data = 0, other = 0;
548         char bssid[256], channel[256], ssid[256], percent[256];
549         float f;
550         GtkListStore *store;
551         GtkTreeSelection *sel;
552         GtkTreeModel *model;
553         GtkTreeIter iter;
554
555         store = GTK_LIST_STORE(gtk_tree_view_get_model(hs->table));
556         hs->num_entries = 0;
557
558         for(tmp = list; tmp; tmp=tmp->next) {
559
560                 if (hs->show_only_existing && tmp->is_broadcast) {
561                         if (tmp->iter_valid) {
562                                 gtk_list_store_remove(store, &tmp->iter);
563                                 tmp->iter_valid = FALSE;
564                         }
565                         continue;
566                 }
567
568                 data = tmp->type[0x20] + tmp->type[0x21] + tmp->type[0x22] + tmp->type[0x23] +
569                   tmp->type[0x28] + tmp->type[0x29] + tmp->type[0x2A] + tmp->type[0x2B];
570                 other = tmp->number_of_packets - data - tmp->type[0x08] - tmp->type[0x04] -
571                   tmp->type[0x05] - tmp->type[0x0B] - tmp->type[0x0C];
572                 f = (float)(((float)tmp->number_of_packets * 100.0) / hs->number_of_packets);
573
574                 if (hs->resolve_names) {
575                         g_strlcpy (bssid, get_addr_name(&tmp->bssid), sizeof(bssid));
576                 } else {
577                         g_strlcpy (bssid, ep_address_to_str(&tmp->bssid), sizeof(bssid));
578                 }
579                 if (tmp->stats.channel) {
580                         g_snprintf (channel, sizeof(channel), "%u", tmp->stats.channel);
581                 } else {
582                         channel[0] = '\0';
583                 }
584                 if (tmp->stats.ssid_len == 0) {
585                         g_strlcpy (ssid, "<Broadcast>", sizeof(ssid));
586                 } else if (tmp->stats.ssid_len == 1 && tmp->stats.ssid[0] == 0) {
587                         g_strlcpy (ssid, "<Hidden>", sizeof(ssid));
588                 } else {
589                         g_strlcpy (ssid, format_text(tmp->stats.ssid, tmp->stats.ssid_len), sizeof(ssid));
590                 }
591                 g_snprintf (percent, sizeof(percent), "%.2f %%", f);
592
593                 if (!tmp->iter_valid) {
594                         gtk_list_store_append(store, &tmp->iter);
595                         tmp->iter_valid = TRUE;
596                 }
597                 gtk_list_store_set (store, &tmp->iter,
598                                     BSSID_COLUMN, bssid,
599                                     CHANNEL_COLUMN, channel,
600                                     SSID_COLUMN, ssid,
601                                     PERCENT_COLUMN, percent,
602                                     BEACONS_COLUMN, tmp->type[0x08],
603                                     DATA_COLUMN, data,
604                                     PROBE_REQ_COLUMN, tmp->type[0x04],
605                                     PROBE_RESP_COLUMN, tmp->type[0x05],
606                                     AUTH_COLUMN, tmp->type[0x0B],
607                                     DEAUTH_COLUMN, tmp->type[0x0C],
608                                     OTHER_COLUMN, other,
609                                     PROTECTION_COLUMN, tmp->stats.protection,
610                                     PERCENT_VALUE_COLUMN, f,
611                                     TABLE_COLUMN, tmp,
612                                     -1);
613
614                 hs->num_entries++;
615         }
616
617         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW(hs->table));
618         if (gtk_tree_selection_get_selected (sel, &model, &iter)) {
619                 wlan_ep_t *ep;
620
621                 gtk_tree_model_get (model, &iter, TABLE_COLUMN, &ep, -1);
622                 wlanstat_draw_details (hs, ep, FALSE);
623         }
624 }
625
626 /* What to do when a list item is selected/unselected */
627 static void
628 wlan_select_cb(GtkTreeSelection *sel, gpointer data)
629 {
630         wlanstat_t *hs = (wlanstat_t *)data;
631         wlan_ep_t *ep;
632         GtkTreeModel *model;
633         GtkTreeIter iter;
634
635         if (gtk_tree_selection_get_selected (sel, &model, &iter)) {
636                 gtk_tree_model_get (model, &iter, TABLE_COLUMN, &ep, -1);
637                 wlanstat_draw_details (hs, ep, TRUE);
638         }
639 }
640
641
642 static void
643 wlan_resolve_toggle_dest(GtkWidget *widget, gpointer data)
644 {
645         wlanstat_t *hs = (wlanstat_t *)data;
646
647         hs->resolve_names = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (widget));
648
649         wlanstat_draw(hs);
650 }
651
652 static void
653 wlan_filter_toggle_dest(GtkWidget *widget, gpointer data)
654 {
655         wlanstat_t *hs = (wlanstat_t *)data;
656
657         hs->use_dfilter = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (widget));
658
659         cf_retap_packets(&cfile);
660         gdk_window_raise(wlanstat_dlg_w->window);
661 }
662
663 static void
664 wlan_existing_toggle_dest(GtkWidget *widget, gpointer data)
665 {
666         wlanstat_t *hs = (wlanstat_t *)data;
667
668         hs->show_only_existing = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (widget));
669
670         wlanstat_draw(hs);
671 }
672
673 static gboolean
674 csv_handle(GtkTreeModel *model, GtkTreePath *path _U_, GtkTreeIter *iter,
675               gpointer data)
676 {
677         GString *CSV_str = (GString *)data;
678         gchar   *table_text;
679         gint     table_value;
680         int      i;
681
682         for (i=0; i<=PROTECTION_COLUMN; i++) {
683                 if (i == BSSID_COLUMN || i == CHANNEL_COLUMN || i == SSID_COLUMN ||
684                     i == PERCENT_COLUMN || i == PROTECTION_COLUMN) {
685                         gtk_tree_model_get(model, iter, i, &table_text, -1);
686                         g_string_append_printf(CSV_str, "\"%s\"", table_text);
687                         g_free(table_text);
688                 } else {
689                         gtk_tree_model_get(model, iter, i, &table_value, -1);
690                         g_string_append_printf(CSV_str, "\"%u\"", table_value);
691                 }
692                 if (i != PROTECTION_COLUMN)
693                         g_string_append(CSV_str,",");
694         }
695         g_string_append(CSV_str,"\n");
696
697         return FALSE;
698 }
699
700 static void
701 wlan_copy_as_csv(GtkWindow *win _U_, gpointer data)
702 {
703         int             i;
704         GString         *CSV_str = g_string_new("");
705         GtkClipboard    *cb;
706         GtkTreeView     *tree_view = GTK_TREE_VIEW(data);
707         GtkListStore    *store;
708
709         /* Add the column headers to the CSV data */
710         for (i=0; i<=PROTECTION_COLUMN; i++) {
711                 g_string_append_printf(CSV_str, "\"%s\"", titles[i]);
712                 if (i != PROTECTION_COLUMN)
713                         g_string_append(CSV_str, ",");
714         }
715         g_string_append(CSV_str,"\n");
716
717         /* Add the column values to the CSV data */
718         store = GTK_LIST_STORE(gtk_tree_view_get_model(tree_view));
719         gtk_tree_model_foreach(GTK_TREE_MODEL(store), csv_handle, CSV_str);
720
721         /* Now that we have the CSV data, copy it into the default clipboard */
722         cb = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD);
723         gtk_clipboard_set_text(cb, CSV_str->str, -1);
724         g_string_free(CSV_str, TRUE);
725 }
726
727 static void
728 win_destroy_cb (GtkWindow *win _U_, gpointer data)
729 {
730         wlanstat_t *hs = (wlanstat_t *)data;
731
732         protect_thread_critical_region ();
733         remove_tap_listener (hs);
734         unprotect_thread_critical_region ();
735
736         if (wlanstat_dlg_w != NULL) {
737                 window_destroy(wlanstat_dlg_w);
738                 wlanstat_dlg_w = NULL;
739         }
740         wlanstat_reset (hs);
741         g_free (hs);
742
743         recent.gui_geometry_wlan_stats_pane =
744           gtk_paned_get_position(GTK_PANED(wlanstat_pane));
745 }
746
747 /* Filter value */
748 #define VALUE_BSSID_ONLY       0
749 #define VALUE_SSID_ONLY        1
750 #define VALUE_BSSID_AND_SSID   2
751 #define VALUE_BSSID_OR_SSID    3
752
753 static void
754 wlan_select_filter_cb(GtkWidget *widget _U_, gpointer callback_data, guint callback_action)
755 {
756         int value;
757         wlanstat_t *hs=(wlanstat_t *)callback_data;
758         char *str = NULL;
759         wlan_ep_t *ep;
760         GtkTreeSelection *sel;
761         GtkTreeModel *model;
762         GtkTreeIter iter;
763
764         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW(hs->table));
765         gtk_tree_selection_get_selected (sel, &model, &iter);
766         gtk_tree_model_get (model, &iter, TABLE_COLUMN, &ep, -1);
767
768         value = FILTER_EXTRA(callback_action);
769
770         switch (value) {
771         case VALUE_BSSID_ONLY:
772                 str = g_strdup_printf("wlan.bssid==%s", ep_address_to_str(&ep->bssid));
773                 break;
774         case VALUE_SSID_ONLY:
775                 str = g_strdup_printf("wlan_mgt.ssid==\"%s\"", format_text(ep->stats.ssid, ep->stats.ssid_len));
776                 break;
777         case VALUE_BSSID_AND_SSID:
778                 str = g_strdup_printf("wlan.bssid==%s && wlan_mgt.ssid==\"%s\"",
779                                       ep_address_to_str(&ep->bssid), format_text(ep->stats.ssid, ep->stats.ssid_len));
780                 break;
781         case VALUE_BSSID_OR_SSID:
782                 str = g_strdup_printf("wlan.bssid==%s || wlan_mgt.ssid==\"%s\"",
783                                       ep_address_to_str(&ep->bssid), format_text(ep->stats.ssid, ep->stats.ssid_len));
784                 break;
785         }
786
787         apply_selected_filter (callback_action, str);
788
789         g_free (str);
790 }
791
792 static void
793 wlan_details_select_filter_cb(GtkWidget *widget _U_, gpointer callback_data, guint callback_action)
794 {
795         wlanstat_t *hs=(wlanstat_t *)callback_data;
796         char *str = NULL;
797         wlan_details_ep_t *ep;
798         GtkTreeSelection *sel;
799         GtkTreeModel *model;
800         GtkTreeIter iter;
801
802         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW(hs->details));
803         gtk_tree_selection_get_selected (sel, &model, &iter);
804         gtk_tree_model_get (model, &iter, DETAILS_COLUMN, &ep, -1);
805
806         str = g_strdup_printf("wlan.addr==%s", ep_address_to_str(&ep->addr));
807
808         apply_selected_filter (callback_action, str);
809
810         g_free (str);
811 }
812
813 static gboolean
814 wlan_show_popup_menu_cb(void *widg _U_, GdkEvent *event, wlanstat_t *et)
815 {
816         GdkEventButton *bevent = (GdkEventButton *)event;
817         GtkTreeSelection *sel;
818         GtkTreeModel *model;
819         GtkTreeIter iter;
820
821         /* To qoute the "Gdk Event Structures" doc:
822          * "Normally button 1 is the left mouse button, 2 is the middle button, and 3 is the right button" */
823         if(event->type==GDK_BUTTON_PRESS && bevent->button==3){
824                 /* If this is a right click on one of our columns, popup the context menu */
825                 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW(et->table));
826                 if (gtk_tree_selection_get_selected (sel, &model, &iter)) {
827                         gtk_menu_popup(GTK_MENU(et->menu), NULL, NULL, NULL, NULL,
828                                        bevent->button, bevent->time);
829                 }
830         }
831
832         return FALSE;
833 }
834
835 /* Apply as Filter/Selected */
836 static void
837 wlan_select_filter_as_selected_BSSID_cb(GtkWidget *widget, gpointer user_data)
838 {
839         wlan_select_filter_cb( widget , user_data, CALLBACK_MATCH(ACTYPE_SELECTED, VALUE_BSSID_ONLY));
840 }
841
842 static void
843 wlan_select_filter_as_selected_SSID_cb(GtkWidget *widget, gpointer user_data)
844 {
845         wlan_select_filter_cb( widget , user_data, CALLBACK_MATCH(ACTYPE_SELECTED, VALUE_SSID_ONLY));
846 }
847
848 static void
849 wlan_select_filter_as_selected_BSSID_and_SSID_cb(GtkWidget *widget, gpointer user_data)
850 {
851         wlan_select_filter_cb( widget , user_data, CALLBACK_MATCH(ACTYPE_SELECTED, VALUE_BSSID_AND_SSID));
852 }
853
854 static void
855 wlan_select_filter_as_selected_BSSID_or_SSID_cb(GtkWidget *widget, gpointer user_data)
856 {
857         wlan_select_filter_cb( widget , user_data, CALLBACK_MATCH(ACTYPE_SELECTED, VALUE_BSSID_OR_SSID));
858 }
859
860 /* Apply as Filter/Not Selected */
861 static void
862 wlan_select_filter_as_not_selected_BSSID_cb(GtkWidget *widget, gpointer user_data)
863 {
864         wlan_select_filter_cb( widget , user_data, CALLBACK_MATCH(ACTYPE_NOT_SELECTED, VALUE_BSSID_ONLY));
865 }
866
867 static void
868 wlan_select_filter_as_not_selected_SSID_cb(GtkWidget *widget, gpointer user_data)
869 {
870         wlan_select_filter_cb( widget , user_data, CALLBACK_MATCH(ACTYPE_NOT_SELECTED, VALUE_SSID_ONLY));
871 }
872
873 static void
874 wlan_select_filter_as_not_selected_BSSID_and_SSID_cb(GtkWidget *widget, gpointer user_data)
875 {
876         wlan_select_filter_cb( widget , user_data, CALLBACK_MATCH(ACTYPE_NOT_SELECTED, VALUE_BSSID_AND_SSID));
877 }
878
879 static void
880 wlan_select_filter_as_not_selected_BSSID_or_SSID_cb(GtkWidget *widget, gpointer user_data)
881 {
882         wlan_select_filter_cb( widget , user_data, CALLBACK_MATCH(ACTYPE_NOT_SELECTED, VALUE_BSSID_OR_SSID));
883 }
884
885 /* /Apply as Filter/... and Selected */
886 static void
887 wlan_select_filter_and_selected_BSSID_cb(GtkWidget *widget, gpointer user_data)
888 {
889         wlan_select_filter_cb( widget , user_data, CALLBACK_MATCH(ACTYPE_AND_SELECTED, VALUE_BSSID_ONLY));
890 }
891
892 static void
893 wlan_select_filter_and_selected_SSID_cb(GtkWidget *widget, gpointer user_data)
894 {
895         wlan_select_filter_cb( widget , user_data, CALLBACK_MATCH(ACTYPE_AND_SELECTED, VALUE_SSID_ONLY));
896 }
897
898 static void
899 wlan_select_filter_and_selected_BSSID_and_SSID_cb(GtkWidget *widget, gpointer user_data)
900 {
901         wlan_select_filter_cb( widget , user_data, CALLBACK_MATCH(ACTYPE_AND_SELECTED, VALUE_BSSID_AND_SSID));
902 }
903
904 static void
905 wlan_select_filter_and_selected_BSSID_or_SSID_cb(GtkWidget *widget, gpointer user_data)
906 {
907         wlan_select_filter_cb( widget , user_data, CALLBACK_MATCH(ACTYPE_AND_SELECTED, VALUE_BSSID_OR_SSID));
908 }
909
910 /* /Apply as Filter/... or Selected */
911 static void
912 wlan_select_filter_or_selected_BSSID_cb(GtkWidget *widget, gpointer user_data)
913 {
914         wlan_select_filter_cb( widget , user_data, CALLBACK_MATCH(ACTYPE_OR_SELECTED, VALUE_BSSID_ONLY));
915 }
916
917 static void
918 wlan_select_filter_or_selected_SSID_cb(GtkWidget *widget, gpointer user_data)
919 {
920         wlan_select_filter_cb( widget , user_data, CALLBACK_MATCH(ACTYPE_OR_SELECTED, VALUE_SSID_ONLY));
921 }
922
923 static void
924 wlan_select_filter_or_selected_BSSID_and_SSID_cb(GtkWidget *widget, gpointer user_data)
925 {
926         wlan_select_filter_cb( widget , user_data, CALLBACK_MATCH(ACTYPE_OR_SELECTED, VALUE_BSSID_AND_SSID));
927 }
928
929 static void
930 wlan_select_filter_or_selected_BSSID_or_SSID_cb(GtkWidget *widget, gpointer user_data)
931 {
932         wlan_select_filter_cb( widget , user_data, CALLBACK_MATCH(ACTYPE_OR_SELECTED, VALUE_BSSID_OR_SSID));
933 }
934
935 /* /Apply as Filter/... and not Selected */
936 static void
937 wlan_select_filter_and_not_selected_BSSID_cb(GtkWidget *widget, gpointer user_data)
938 {
939         wlan_select_filter_cb( widget , user_data, CALLBACK_MATCH(ACTYPE_AND_NOT_SELECTED, VALUE_BSSID_ONLY));
940 }
941
942 static void
943 wlan_select_filter_and_not_selected_SSID_cb(GtkWidget *widget, gpointer user_data)
944 {
945         wlan_select_filter_cb( widget , user_data, CALLBACK_MATCH(ACTYPE_AND_NOT_SELECTED, VALUE_SSID_ONLY));
946 }
947
948 static void
949 wlan_select_filter_and_not_selected_BSSID_and_SSID_cb(GtkWidget *widget, gpointer user_data)
950 {
951         wlan_select_filter_cb( widget , user_data, CALLBACK_MATCH(ACTYPE_AND_NOT_SELECTED, VALUE_BSSID_AND_SSID));
952 }
953
954 static void
955 wlan_select_filter_and_not_selected_BSSID_or_SSID_cb(GtkWidget *widget, gpointer user_data)
956 {
957         wlan_select_filter_cb( widget , user_data, CALLBACK_MATCH(ACTYPE_AND_NOT_SELECTED, VALUE_BSSID_OR_SSID));
958 }
959
960 /* /Apply as Filter/... or not Selected */
961 static void
962 wlan_select_filter_or_not_selected_BSSID_cb(GtkWidget *widget, gpointer user_data)
963 {
964         wlan_select_filter_cb( widget , user_data, CALLBACK_MATCH(ACTYPE_OR_NOT_SELECTED, VALUE_BSSID_ONLY));
965 }
966
967 static void
968 wlan_select_filter_or_not_selected_SSID_cb(GtkWidget *widget, gpointer user_data)
969 {
970         wlan_select_filter_cb( widget , user_data, CALLBACK_MATCH(ACTYPE_OR_NOT_SELECTED, VALUE_SSID_ONLY));
971 }
972
973 static void
974 wlan_select_filter_or_not_selected_BSSID_and_SSID_cb(GtkWidget *widget, gpointer user_data)
975 {
976         wlan_select_filter_cb( widget , user_data, CALLBACK_MATCH(ACTYPE_OR_NOT_SELECTED, VALUE_BSSID_AND_SSID));
977 }
978
979 static void
980 wlan_select_filter_or_not_selected_BSSID_or_SSID_cb(GtkWidget *widget, gpointer user_data)
981 {
982         wlan_select_filter_cb( widget , user_data, CALLBACK_MATCH(ACTYPE_OR_NOT_SELECTED, VALUE_BSSID_OR_SSID));
983 }
984
985 /* Prepare */
986 /* Prepare a Filter/Selected */
987 static void
988 wlan_prepare_filter_as_selected_BSSID_cb(GtkWidget *widget, gpointer user_data)
989 {
990         wlan_select_filter_cb( widget , user_data, CALLBACK_PREPARE(ACTYPE_SELECTED, VALUE_BSSID_ONLY));
991 }
992
993 static void
994 wlan_prepare_filter_as_selected_SSID_cb(GtkWidget *widget, gpointer user_data)
995 {
996         wlan_select_filter_cb( widget , user_data, CALLBACK_PREPARE(ACTYPE_SELECTED, VALUE_SSID_ONLY));
997 }
998
999 static void
1000 wlan_prepare_filter_as_selected_BSSID_and_SSID_cb(GtkWidget *widget, gpointer user_data)
1001 {
1002         wlan_select_filter_cb( widget , user_data, CALLBACK_PREPARE(ACTYPE_SELECTED, VALUE_BSSID_AND_SSID));
1003 }
1004
1005 static void
1006 wlan_prepare_filter_as_selected_BSSID_or_SSID_cb(GtkWidget *widget, gpointer user_data)
1007 {
1008         wlan_select_filter_cb( widget , user_data, CALLBACK_PREPARE(ACTYPE_SELECTED, VALUE_BSSID_OR_SSID));
1009 }
1010
1011 /* Prepare a Filter/Not Selected */
1012 static void
1013 wlan_prepare_filter_as_not_selected_BSSID_cb(GtkWidget *widget, gpointer user_data)
1014 {
1015         wlan_select_filter_cb( widget , user_data, CALLBACK_PREPARE(ACTYPE_NOT_SELECTED, VALUE_BSSID_ONLY));
1016 }
1017
1018 static void
1019 wlan_prepare_filter_as_not_selected_SSID_cb(GtkWidget *widget, gpointer user_data)
1020 {
1021         wlan_select_filter_cb( widget , user_data, CALLBACK_PREPARE(ACTYPE_NOT_SELECTED, VALUE_SSID_ONLY));
1022 }
1023
1024 static void
1025 wlan_prepare_filter_as_not_selected_BSSID_and_SSID_cb(GtkWidget *widget, gpointer user_data)
1026 {
1027         wlan_select_filter_cb( widget , user_data, CALLBACK_PREPARE(ACTYPE_NOT_SELECTED, VALUE_BSSID_AND_SSID));
1028 }
1029
1030 static void
1031 wlan_prepare_filter_as_not_selected_BSSID_or_SSID_cb(GtkWidget *widget, gpointer user_data)
1032 {
1033         wlan_select_filter_cb( widget , user_data, CALLBACK_PREPARE(ACTYPE_NOT_SELECTED, VALUE_BSSID_OR_SSID));
1034 }
1035
1036 /* /Prepare a Filter/... and Selected */
1037 static void
1038 wlan_prepare_filter_and_selected_BSSID_cb(GtkWidget *widget, gpointer user_data)
1039 {
1040         wlan_select_filter_cb( widget , user_data, CALLBACK_PREPARE(ACTYPE_AND_SELECTED, VALUE_BSSID_ONLY));
1041 }
1042
1043 static void
1044 wlan_prepare_filter_and_selected_SSID_cb(GtkWidget *widget, gpointer user_data)
1045 {
1046         wlan_select_filter_cb( widget , user_data, CALLBACK_PREPARE(ACTYPE_AND_SELECTED, VALUE_SSID_ONLY));
1047 }
1048
1049 static void
1050 wlan_prepare_filter_and_selected_BSSID_and_SSID_cb(GtkWidget *widget, gpointer user_data)
1051 {
1052         wlan_select_filter_cb( widget , user_data, CALLBACK_PREPARE(ACTYPE_AND_SELECTED, VALUE_BSSID_AND_SSID));
1053 }
1054
1055 static void
1056 wlan_prepare_filter_and_selected_BSSID_or_SSID_cb(GtkWidget *widget, gpointer user_data)
1057 {
1058         wlan_select_filter_cb( widget , user_data, CALLBACK_PREPARE(ACTYPE_AND_SELECTED, VALUE_BSSID_OR_SSID));
1059 }
1060
1061 /* /Prepare a Filter/... or Selected */
1062 static void
1063 wlan_prepare_filter_or_selected_BSSID_cb(GtkWidget *widget, gpointer user_data)
1064 {
1065         wlan_select_filter_cb( widget , user_data, CALLBACK_PREPARE(ACTYPE_OR_SELECTED, VALUE_BSSID_ONLY));
1066 }
1067
1068 static void
1069 wlan_prepare_filter_or_selected_SSID_cb(GtkWidget *widget, gpointer user_data)
1070 {
1071         wlan_select_filter_cb( widget , user_data, CALLBACK_PREPARE(ACTYPE_OR_SELECTED, VALUE_SSID_ONLY));
1072 }
1073
1074 static void
1075 wlan_prepare_filter_or_selected_BSSID_and_SSID_cb(GtkWidget *widget, gpointer user_data)
1076 {
1077         wlan_select_filter_cb( widget , user_data, CALLBACK_PREPARE(ACTYPE_OR_SELECTED, VALUE_BSSID_AND_SSID));
1078 }
1079
1080 static void
1081 wlan_prepare_filter_or_selected_BSSID_or_SSID_cb(GtkWidget *widget, gpointer user_data)
1082 {
1083         wlan_select_filter_cb( widget , user_data, CALLBACK_PREPARE(ACTYPE_OR_SELECTED, VALUE_BSSID_OR_SSID));
1084 }
1085
1086 /* /Prepare a Filter/... and not Selected */
1087 static void
1088 wlan_prepare_filter_and_not_selected_BSSID_cb(GtkWidget *widget, gpointer user_data)
1089 {
1090         wlan_select_filter_cb( widget , user_data, CALLBACK_PREPARE(ACTYPE_AND_NOT_SELECTED, VALUE_BSSID_ONLY));
1091 }
1092
1093 static void
1094 wlan_prepare_filter_and_not_selected_SSID_cb(GtkWidget *widget, gpointer user_data)
1095 {
1096         wlan_select_filter_cb( widget , user_data, CALLBACK_PREPARE(ACTYPE_AND_NOT_SELECTED, VALUE_SSID_ONLY));
1097 }
1098
1099 static void
1100 wlan_prepare_filter_and_not_selected_BSSID_and_SSID_cb(GtkWidget *widget, gpointer user_data)
1101 {
1102         wlan_select_filter_cb( widget , user_data, CALLBACK_PREPARE(ACTYPE_AND_NOT_SELECTED, VALUE_BSSID_AND_SSID));
1103 }
1104
1105 static void
1106 wlan_prepare_filter_and_not_selected_BSSID_or_SSID_cb(GtkWidget *widget, gpointer user_data)
1107 {
1108         wlan_select_filter_cb( widget , user_data, CALLBACK_PREPARE(ACTYPE_AND_NOT_SELECTED, VALUE_BSSID_OR_SSID));
1109 }
1110
1111 /* /Prepare a Filter/... or not Selected */
1112 static void
1113 wlan_prepare_filter_or_not_selected_BSSID_cb(GtkWidget *widget, gpointer user_data)
1114 {
1115         wlan_select_filter_cb( widget , user_data, CALLBACK_PREPARE(ACTYPE_OR_NOT_SELECTED, VALUE_BSSID_ONLY));
1116 }
1117
1118 static void
1119 wlan_prepare_filter_or_not_selected_SSID_cb(GtkWidget *widget, gpointer user_data)
1120 {
1121         wlan_select_filter_cb( widget , user_data, CALLBACK_PREPARE(ACTYPE_OR_NOT_SELECTED, VALUE_SSID_ONLY));
1122 }
1123
1124 static void
1125 wlan_prepare_filter_or_not_selected_BSSID_and_SSID_cb(GtkWidget *widget, gpointer user_data)
1126 {
1127         wlan_select_filter_cb( widget , user_data, CALLBACK_PREPARE(ACTYPE_OR_NOT_SELECTED, VALUE_BSSID_AND_SSID));
1128 }
1129 static void
1130 wlan_prepare_filter_or_not_selected_BSSID_or_SSID_cb(GtkWidget *widget, gpointer user_data)
1131 {
1132         wlan_select_filter_cb( widget , user_data, CALLBACK_PREPARE(ACTYPE_OR_NOT_SELECTED, VALUE_BSSID_OR_SSID));
1133 }
1134
1135 /* /Find frame/Find Frame/ */
1136 static void
1137 wlan_find_frame_BSSID_cb(GtkWidget *widget, gpointer user_data)
1138 {
1139         wlan_select_filter_cb( widget , user_data, CALLBACK_FIND_FRAME(ACTYPE_SELECTED, VALUE_BSSID_ONLY));
1140 }
1141 static void
1142 wlan_find_frame_SSID_cb(GtkWidget *widget, gpointer user_data)
1143 {
1144         wlan_select_filter_cb( widget , user_data, CALLBACK_FIND_FRAME(ACTYPE_SELECTED, VALUE_SSID_ONLY));
1145 }
1146 static void
1147 wlan_find_frame_BSSID_and_SSID_cb(GtkWidget *widget, gpointer user_data)
1148 {
1149         wlan_select_filter_cb( widget , user_data, CALLBACK_FIND_FRAME(ACTYPE_SELECTED, VALUE_BSSID_AND_SSID));
1150 }
1151 static void
1152 wlan_find_frame_BSSID_or_SSID_cb(GtkWidget *widget, gpointer user_data)
1153 {
1154         wlan_select_filter_cb( widget , user_data, CALLBACK_FIND_FRAME(ACTYPE_SELECTED, VALUE_BSSID_OR_SSID));
1155 }
1156
1157 /* /Find frame/Find Next/ */
1158 static void
1159 wlan_find_frame_next_BSSID_cb(GtkWidget *widget, gpointer user_data)
1160 {
1161         wlan_select_filter_cb( widget , user_data, CALLBACK_FIND_NEXT(ACTYPE_SELECTED, VALUE_BSSID_ONLY));
1162 }
1163 static void
1164 wlan_find_frame_next_SSID_cb(GtkWidget *widget, gpointer user_data)
1165 {
1166         wlan_select_filter_cb( widget , user_data, CALLBACK_FIND_NEXT(ACTYPE_SELECTED, VALUE_SSID_ONLY));
1167 }
1168 static void
1169 wlan_find_frame_next_BSSID_and_SSID_cb(GtkWidget *widget, gpointer user_data)
1170 {
1171         wlan_select_filter_cb( widget , user_data, CALLBACK_FIND_NEXT(ACTYPE_SELECTED, VALUE_BSSID_AND_SSID));
1172 }
1173 static void
1174 wlan_find_frame_next_BSSID_or_SSID_cb(GtkWidget *widget, gpointer user_data)
1175 {
1176         wlan_select_filter_cb( widget , user_data, CALLBACK_FIND_NEXT(ACTYPE_SELECTED, VALUE_BSSID_OR_SSID));
1177 }
1178 /* /Find frame/Find Previous/ */
1179 static void
1180 wlan_find_frame_previous_BSSID_cb(GtkWidget *widget, gpointer user_data)
1181 {
1182         wlan_select_filter_cb( widget , user_data, CALLBACK_FIND_PREVIOUS(ACTYPE_SELECTED, VALUE_BSSID_ONLY));
1183 }
1184 static void
1185 wlan_find_frame_previous_SSID_cb(GtkWidget *widget, gpointer user_data)
1186 {
1187         wlan_select_filter_cb( widget , user_data, CALLBACK_FIND_PREVIOUS(ACTYPE_SELECTED, VALUE_SSID_ONLY));
1188 }
1189 static void
1190 wlan_find_frame_previous_BSSID_and_SSID_cb(GtkWidget *widget, gpointer user_data)
1191 {
1192         wlan_select_filter_cb( widget , user_data, CALLBACK_FIND_PREVIOUS(ACTYPE_SELECTED, VALUE_BSSID_AND_SSID));
1193 }
1194 static void
1195 wlan_find_frame_previous_BSSID_or_SSID_cb(GtkWidget *widget, gpointer user_data)
1196 {
1197         wlan_select_filter_cb( widget , user_data, CALLBACK_FIND_PREVIOUS(ACTYPE_SELECTED, VALUE_BSSID_OR_SSID));
1198 }
1199
1200 /* /Colorize/ */
1201 static void
1202 wlan_colorize_BSSID_cb(GtkWidget *widget, gpointer user_data)
1203 {
1204         wlan_select_filter_cb( widget , user_data, CALLBACK_COLORIZE(ACTYPE_SELECTED, VALUE_BSSID_ONLY));
1205 }
1206 static void
1207 wlan_colorize_SSID_cb(GtkWidget *widget, gpointer user_data)
1208 {
1209         wlan_select_filter_cb( widget , user_data, CALLBACK_COLORIZE(ACTYPE_SELECTED, VALUE_SSID_ONLY));
1210 }
1211 static void
1212 wlan_colorize_BSSID_and_SSID_cb(GtkWidget *widget, gpointer user_data)
1213 {
1214         wlan_select_filter_cb( widget , user_data, CALLBACK_COLORIZE(ACTYPE_SELECTED, VALUE_BSSID_AND_SSID));
1215 }
1216 static void
1217 wlan_colorize_BSSID_or_SSID_cb(GtkWidget *widget, gpointer user_data)
1218 {
1219         wlan_select_filter_cb( widget , user_data, CALLBACK_COLORIZE(ACTYPE_SELECTED, VALUE_BSSID_OR_SSID));
1220 }
1221
1222
1223 static const char *ui_desc_wlan_stat_filter_popup =
1224 "<ui>\n"
1225 "  <popup name='WlanStatFilterPopup' action='PopupAction'>\n"
1226 "    <menu name= 'ApplyAsFilter' action='/Apply as Filter'>\n"
1227 "        <menu name= 'ApplyAsFilterSelected' action='/Apply as Filter/Selected'>\n"
1228 "            <menuitem action='/Apply as Filter/Selected/BSSID'/>\n"
1229 "            <menuitem action='/Apply as Filter/Selected/SSID'/>\n"
1230 "            <menuitem action='/Apply as Filter/Selected/BSSID and SSID'/>\n"
1231 "            <menuitem action='/Apply as Filter/Selected/BSSID or SSID'/>\n"
1232 "        </menu>\n"
1233 "        <menu name= 'ApplyAsFilterNotSelected' action='/Apply as Filter/Not Selected'>\n"
1234 "            <menuitem action='/Apply as Filter/Not Selected/BSSID'/>\n"
1235 "            <menuitem action='/Apply as Filter/Not Selected/SSID'/>\n"
1236 "            <menuitem action='/Apply as Filter/Not Selected/BSSID and SSID'/>\n"
1237 "            <menuitem action='/Apply as Filter/Not Selected/BSSID or SSID'/>\n"
1238 "        </menu>\n"
1239 "        <menu name= 'ApplyAsFilterAndSelected' action='/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " and Selected'>\n"
1240 "            <menuitem action='/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " and Selected/BSSID'/>\n"
1241 "            <menuitem action='/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " and Selected/SSID'/>\n"
1242 "            <menuitem action='/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " and Selected/BSSID and SSID'/>\n"
1243 "            <menuitem action='/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " and Selected/BSSID or SSID'/>\n"
1244 "        </menu>\n"
1245 "        <menu name= 'ApplyAsFilterOrSelected' action='/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " or Selected'>\n"
1246 "            <menuitem action='/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " or Selected/BSSID'/>\n"
1247 "            <menuitem action='/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " or Selected/SSID'/>\n"
1248 "            <menuitem action='/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " or Selected/BSSID and SSID'/>\n"
1249 "            <menuitem action='/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " or Selected/BSSID or SSID'/>\n"
1250 "        </menu>\n"
1251 "        <menu name= 'ApplyAsFilterAndNotSelected' action='/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " and not Selected'>\n"
1252 "            <menuitem action='/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " and not Selected/BSSID'/>\n"
1253 "            <menuitem action='/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " and not Selected/SSID'/>\n"
1254 "            <menuitem action='/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " and not Selected/BSSID and SSID'/>\n"
1255 "            <menuitem action='/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " and not Selected/BSSID or SSID'/>\n"
1256 "        </menu>\n"
1257 "        <menu name= 'ApplyAsFilterOrNotSelected' action='/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " or not Selected'>\n"
1258 "            <menuitem action='/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " or not Selected/BSSID'/>\n"
1259 "            <menuitem action='/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " or not Selected/SSID'/>\n"
1260 "            <menuitem action='/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " or not Selected/BSSID and SSID'/>\n"
1261 "            <menuitem action='/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " or not Selected/BSSID or SSID'/>\n"
1262 "        </menu>\n"
1263 "    </menu>\n"
1264 "    <menu name= 'PrepareAFilter' action='/Prepare a Filter'>\n"
1265 "        <menu name= 'PrepareAFilterSelected' action='/Prepare a Filter/Selected'>\n"
1266 "            <menuitem action='/Prepare a Filter/Selected/BSSID'/>\n"
1267 "            <menuitem action='/Prepare a Filter/Selected/SSID'/>\n"
1268 "            <menuitem action='/Prepare a Filter/Selected/BSSID and SSID'/>\n"
1269 "            <menuitem action='/Prepare a Filter/Selected/BSSID or SSID'/>\n"
1270 "        </menu>\n"
1271 "        <menu name= 'PrepareAFilterNotSelected' action='/Prepare a Filter/Not Selected'>\n"
1272 "            <menuitem action='/Prepare a Filter/Not Selected/BSSID'/>\n"
1273 "            <menuitem action='/Prepare a Filter/Not Selected/SSID'/>\n"
1274 "            <menuitem action='/Prepare a Filter/Not Selected/BSSID and SSID'/>\n"
1275 "            <menuitem action='/Prepare a Filter/Not Selected/BSSID or SSID'/>\n"
1276 "        </menu>\n"
1277 "        <menu name= 'PrepareAFilterAndSelected' action='/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " and Selected'>\n"
1278 "            <menuitem action='/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " and Selected/BSSID'/>\n"
1279 "            <menuitem action='/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " and Selected/SSID'/>\n"
1280 "            <menuitem action='/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " and Selected/BSSID and SSID'/>\n"
1281 "            <menuitem action='/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " and Selected/BSSID or SSID'/>\n"
1282 "        </menu>\n"
1283 "        <menu name= 'PrepareAFilterOrSelected' action='/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " or Selected'>\n"
1284 "            <menuitem action='/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " or Selected/BSSID'/>\n"
1285 "            <menuitem action='/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " or Selected/SSID'/>\n"
1286 "            <menuitem action='/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " or Selected/BSSID and SSID'/>\n"
1287 "            <menuitem action='/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " or Selected/BSSID or SSID'/>\n"
1288 "        </menu>\n"
1289 "        <menu name= 'PrepareAFilterAndNotSelected' action='/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " and not Selected'>\n"
1290 "            <menuitem action='/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " and not Selected/BSSID'/>\n"
1291 "            <menuitem action='/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " and not Selected/SSID'/>\n"
1292 "            <menuitem action='/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " and not Selected/BSSID and SSID'/>\n"
1293 "            <menuitem action='/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " and not Selected/BSSID or SSID'/>\n"
1294 "        </menu>\n"
1295 "        <menu name= 'PrepareAFilterOrNotSelected' action='/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " or not Selected'>\n"
1296 "            <menuitem action='/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " or not Selected/BSSID'/>\n"
1297 "            <menuitem action='/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " or not Selected/SSID'/>\n"
1298 "            <menuitem action='/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " or not Selected/BSSID and SSID'/>\n"
1299 "            <menuitem action='/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " or not Selected/BSSID or SSID'/>\n"
1300 "        </menu>\n"
1301 "    </menu>\n"
1302 "    <menu name= 'FindFrame' action='/Find Frame'>\n"
1303 "        <menu name= 'FindFrameFindFrame' action='/Find Frame/Find Frame'>\n"
1304 "            <menuitem action='/Find Frame/Find Frame/BSSID'/>\n"
1305 "            <menuitem action='/Find Frame/Find Frame/SSID'/>\n"
1306 "            <menuitem action='/Find Frame/Find Frame/BSSID and SSID'/>\n"
1307 "            <menuitem action='/Find Frame/Find Frame/BSSID or SSID'/>\n"
1308 "        </menu>\n"
1309 "        <menu name= 'FindFrameNext' action='/Find Frame/Find Next'>\n"
1310 "            <menuitem action='/Find Frame/Find Next/BSSID'/>\n"
1311 "            <menuitem action='/Find Frame/Find Next/SSID'/>\n"
1312 "            <menuitem action='/Find Frame/Find Next/BSSID and SSID'/>\n"
1313 "            <menuitem action='/Find Frame/Find Next/BSSID or SSID'/>\n"
1314 "        </menu>\n"
1315 "        <menu name= 'FindFramePrevious' action='/Find Frame/Find Previous'>\n"
1316 "            <menuitem action='/Find Frame/Find Previous/BSSID'/>\n"
1317 "            <menuitem action='/Find Frame/Find Previous/SSID'/>\n"
1318 "            <menuitem action='/Find Frame/Find Previous/BSSID and SSID'/>\n"
1319 "            <menuitem action='/Find Frame/Find Previous/BSSID or SSID'/>\n"
1320 "        </menu>\n"
1321 "    </menu>\n"
1322 "    <menu name= 'Colorize' action='/Colorize'>\n"
1323 "        <menuitem action='/Colorize/BSSID'/>\n"
1324 "        <menuitem action='/Colorize/SSID'/>\n"
1325 "        <menuitem action='/Colorize/BSSID and SSID'/>\n"
1326 "        <menuitem action='/Colorize/BSSID or SSID'/>\n"
1327 "    </menu>\n"
1328 "  </popup>\n"
1329 "</ui>\n";
1330
1331 /*
1332  * GtkActionEntry
1333  * typedef struct {
1334  *   const gchar     *name;
1335  *   const gchar     *stock_id;
1336  *   const gchar     *label;
1337  *   const gchar     *accelerator;
1338  *   const gchar     *tooltip;
1339  *   GCallback  callback;
1340  * } GtkActionEntry;
1341  * const gchar *name;                   The name of the action.
1342  * const gchar *stock_id;               The stock id for the action, or the name of an icon from the icon theme.
1343  * const gchar *label;                  The label for the action. This field should typically be marked for translation,
1344  *                                                              see gtk_action_group_set_translation_domain().
1345  *                                                              If label is NULL, the label of the stock item with id stock_id is used.
1346  * const gchar *accelerator;    The accelerator for the action, in the format understood by gtk_accelerator_parse().
1347  * const gchar *tooltip;                The tooltip for the action. This field should typically be marked for translation,
1348  *                              see gtk_action_group_set_translation_domain().
1349  * GCallback callback;                  The function to call when the action is activated.
1350  *
1351  */
1352 static const GtkActionEntry wlans_stat_popup_entries[] = {
1353   /* Top level */
1354   { "/Apply as Filter",                         NULL, "Apply as Filter", NULL, NULL, NULL },
1355   { "/Prepare a Filter",                        NULL, "Prepare a Filter", NULL, NULL, NULL },
1356   { "/Find Frame",                                      NULL, "Find Frame", NULL, NULL, NULL },
1357   { "/Colorize",                                        NULL, "Colorize", NULL, NULL, NULL },
1358
1359   /* Apply as */
1360   { "/Apply as Filter/Selected",                                NULL, "Selected" , NULL, NULL, NULL },
1361   { "/Apply as Filter/Not Selected",                    NULL, "Not Selected", NULL, NULL, NULL },
1362   { "/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " and Selected",               NULL, UTF8_HORIZONTAL_ELLIPSIS " and Selected", NULL, NULL, NULL },
1363   { "/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " or Selected",                        NULL, UTF8_HORIZONTAL_ELLIPSIS " or Selected", NULL, NULL, NULL },
1364   { "/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " and not Selected",   NULL, UTF8_HORIZONTAL_ELLIPSIS " and not Selected", NULL, NULL, NULL },
1365   { "/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " or not Selected",            NULL, UTF8_HORIZONTAL_ELLIPSIS " or not Selected", NULL, NULL, NULL },
1366
1367   /* Apply as Selected */
1368   { "/Apply as Filter/Selected/BSSID",                  NULL, "BSSID",                  NULL, "BSSID",                          G_CALLBACK(wlan_select_filter_as_selected_BSSID_cb)},
1369   { "/Apply as Filter/Selected/SSID",                   NULL, "SSID",                   NULL, "SSID",                           G_CALLBACK(wlan_select_filter_as_selected_SSID_cb)},
1370   { "/Apply as Filter/Selected/BSSID and SSID", NULL, "BSSID and SSID", NULL, "BSSID and SSID",         G_CALLBACK(wlan_select_filter_as_selected_BSSID_and_SSID_cb)},
1371   { "/Apply as Filter/Selected/BSSID or SSID",  NULL, "BSSID or SSID",  NULL, "BSSID or SSID",          G_CALLBACK(wlan_select_filter_as_selected_BSSID_or_SSID_cb)},
1372
1373   /* Apply as Not Selected */
1374   { "/Apply as Filter/Not Selected/BSSID",                      NULL, "BSSID",                  NULL, "BSSID",                          G_CALLBACK(wlan_select_filter_as_not_selected_BSSID_cb)},
1375   { "/Apply as Filter/Not Selected/SSID",                       NULL, "SSID",                   NULL, "SSID",                           G_CALLBACK(wlan_select_filter_as_not_selected_SSID_cb)},
1376   { "/Apply as Filter/Not Selected/BSSID and SSID",     NULL, "BSSID and SSID", NULL, "BSSID and SSID",         G_CALLBACK(wlan_select_filter_as_not_selected_BSSID_and_SSID_cb)},
1377   { "/Apply as Filter/Not Selected/BSSID or SSID",      NULL, "BSSID or SSID",  NULL, "BSSID or SSID",          G_CALLBACK(wlan_select_filter_as_not_selected_BSSID_or_SSID_cb)},
1378
1379   /* Apply as and Selected */
1380   { "/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " and Selected/BSSID",                 NULL, "BSSID",                  NULL, "BSSID",                          G_CALLBACK(wlan_select_filter_and_selected_BSSID_cb)},
1381   { "/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " and Selected/SSID",                  NULL, "SSID",                   NULL, "SSID",                           G_CALLBACK(wlan_select_filter_and_selected_SSID_cb)},
1382   { "/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " and Selected/BSSID and SSID",        NULL, "BSSID and SSID", NULL, "BSSID and SSID",         G_CALLBACK(wlan_select_filter_and_selected_BSSID_and_SSID_cb)},
1383   { "/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " and Selected/BSSID or SSID", NULL, "BSSID or SSID",  NULL, "BSSID or SSID",          G_CALLBACK(wlan_select_filter_and_selected_BSSID_or_SSID_cb)},
1384
1385   /* Apply as or Selected */
1386   { "/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " or Selected/BSSID",                  NULL, "BSSID",                  NULL, "BSSID",                          G_CALLBACK(wlan_select_filter_or_selected_BSSID_cb)},
1387   { "/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " or Selected/SSID",                   NULL, "SSID",                   NULL, "SSID",                           G_CALLBACK(wlan_select_filter_or_selected_SSID_cb)},
1388   { "/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " or Selected/BSSID and SSID", NULL, "BSSID and SSID", NULL, "BSSID and SSID",         G_CALLBACK(wlan_select_filter_or_selected_BSSID_and_SSID_cb)},
1389   { "/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " or Selected/BSSID or SSID",  NULL, "BSSID or SSID",  NULL, "BSSID or SSID",          G_CALLBACK(wlan_select_filter_or_selected_BSSID_or_SSID_cb)},
1390
1391   /* /Apply as Filter/... and not Selected */
1392   { "/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " and not Selected/BSSID",                     NULL, "BSSID",                  NULL, "BSSID",                          G_CALLBACK(wlan_select_filter_and_not_selected_BSSID_cb)},
1393   { "/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " and not Selected/SSID",                      NULL, "SSID",                   NULL, "SSID",                           G_CALLBACK(wlan_select_filter_and_not_selected_SSID_cb)},
1394   { "/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " and not Selected/BSSID and SSID",    NULL, "BSSID and SSID", NULL, "BSSID and SSID",         G_CALLBACK(wlan_select_filter_and_not_selected_BSSID_and_SSID_cb)},
1395   { "/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " and not Selected/BSSID or SSID",     NULL, "BSSID or SSID",  NULL, "BSSID or SSID",          G_CALLBACK(wlan_select_filter_and_not_selected_BSSID_or_SSID_cb)},
1396
1397   /* /Apply as Filter/... or not Selected */
1398   { "/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " or not Selected/BSSID",                      NULL, "BSSID",                  NULL, "BSSID",                          G_CALLBACK(wlan_select_filter_or_not_selected_BSSID_cb)},
1399   { "/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " or not Selected/SSID",                       NULL, "SSID",                   NULL, "SSID",                           G_CALLBACK(wlan_select_filter_or_not_selected_SSID_cb)},
1400   { "/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " or not Selected/BSSID and SSID",     NULL, "BSSID and SSID", NULL, "BSSID and SSID",         G_CALLBACK(wlan_select_filter_or_not_selected_BSSID_and_SSID_cb)},
1401   { "/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " or not Selected/BSSID or SSID",      NULL, "BSSID or SSID",  NULL, "BSSID or SSID",          G_CALLBACK(wlan_select_filter_or_not_selected_BSSID_or_SSID_cb)},
1402
1403   /* Prepare a */
1404   { "/Prepare a Filter/Selected",                               NULL, "Selected" , NULL, NULL, NULL },
1405   { "/Prepare a Filter/Not Selected",                   NULL, "Not Selected", NULL, NULL, NULL },
1406   { "/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " and Selected",              NULL, UTF8_HORIZONTAL_ELLIPSIS " and Selected", NULL, NULL, NULL },
1407   { "/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " or Selected",               NULL, UTF8_HORIZONTAL_ELLIPSIS " or Selected", NULL, NULL, NULL },
1408   { "/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " and not Selected",  NULL, UTF8_HORIZONTAL_ELLIPSIS " and not Selected", NULL, NULL, NULL },
1409   { "/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " or not Selected",   NULL, UTF8_HORIZONTAL_ELLIPSIS " or not Selected", NULL, NULL, NULL },
1410
1411   /* Prepare a Selected */
1412   { "/Prepare a Filter/Selected/BSSID",                 NULL, "BSSID",                  NULL, "BSSID",                          G_CALLBACK(wlan_prepare_filter_as_selected_BSSID_cb)},
1413   { "/Prepare a Filter/Selected/SSID",                  NULL, "SSID",                   NULL, "SSID",                           G_CALLBACK(wlan_prepare_filter_as_selected_SSID_cb)},
1414   { "/Prepare a Filter/Selected/BSSID and SSID",NULL, "BSSID and SSID", NULL, "BSSID and SSID",         G_CALLBACK(wlan_prepare_filter_as_selected_BSSID_and_SSID_cb)},
1415   { "/Prepare a Filter/Selected/BSSID or SSID", NULL, "BSSID or SSID",  NULL, "BSSID or SSID",          G_CALLBACK(wlan_prepare_filter_as_selected_BSSID_or_SSID_cb)},
1416
1417   /* Prepare a Not Selected */
1418   { "/Prepare a Filter/Not Selected/BSSID",                     NULL, "BSSID",                  NULL, "BSSID",                          G_CALLBACK(wlan_prepare_filter_as_not_selected_BSSID_cb)},
1419   { "/Prepare a Filter/Not Selected/SSID",                      NULL, "SSID",                   NULL, "SSID",                           G_CALLBACK(wlan_prepare_filter_as_not_selected_SSID_cb)},
1420   { "/Prepare a Filter/Not Selected/BSSID and SSID",NULL, "BSSID and SSID",     NULL, "BSSID and SSID",         G_CALLBACK(wlan_prepare_filter_as_not_selected_BSSID_and_SSID_cb)},
1421   { "/Prepare a Filter/Not Selected/BSSID or SSID",     NULL, "BSSID or SSID",  NULL, "BSSID or SSID",          G_CALLBACK(wlan_prepare_filter_as_not_selected_BSSID_or_SSID_cb)},
1422
1423   /* Prepare a and Selected */
1424   { "/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " and Selected/BSSID",                                NULL, "BSSID",                  NULL, "BSSID",                          G_CALLBACK(wlan_prepare_filter_and_selected_BSSID_cb)},
1425   { "/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " and Selected/SSID",                         NULL, "SSID",                   NULL, "SSID",                           G_CALLBACK(wlan_prepare_filter_and_selected_SSID_cb)},
1426   { "/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " and Selected/BSSID and SSID",       NULL, "BSSID and SSID", NULL, "BSSID and SSID",         G_CALLBACK(wlan_prepare_filter_and_selected_BSSID_and_SSID_cb)},
1427   { "/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " and Selected/BSSID or SSID",                NULL, "BSSID or SSID",  NULL, "BSSID or SSID",          G_CALLBACK(wlan_prepare_filter_and_selected_BSSID_or_SSID_cb)},
1428
1429   /* Prepare a or Selected */
1430   { "/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " or Selected/BSSID",                         NULL, "BSSID",                  NULL, "BSSID",                          G_CALLBACK(wlan_prepare_filter_or_selected_BSSID_cb)},
1431   { "/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " or Selected/SSID",                          NULL, "SSID",                   NULL, "SSID",                           G_CALLBACK(wlan_prepare_filter_or_selected_SSID_cb)},
1432   { "/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " or Selected/BSSID and SSID",                NULL, "BSSID and SSID", NULL, "BSSID and SSID",         G_CALLBACK(wlan_prepare_filter_or_selected_BSSID_and_SSID_cb)},
1433   { "/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " or Selected/BSSID or SSID",         NULL, "BSSID or SSID",  NULL, "BSSID or SSID",          G_CALLBACK(wlan_prepare_filter_or_selected_BSSID_or_SSID_cb)},
1434
1435   /* /Prepare a Filter/... and not Selected */
1436   { "/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " and not Selected/BSSID",                    NULL, "BSSID",                  NULL, "BSSID",                          G_CALLBACK(wlan_prepare_filter_and_not_selected_BSSID_cb)},
1437   { "/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " and not Selected/SSID",                     NULL, "SSID",                   NULL, "SSID",                           G_CALLBACK(wlan_prepare_filter_and_not_selected_SSID_cb)},
1438   { "/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " and not Selected/BSSID and SSID",NULL, "BSSID and SSID",    NULL, "BSSID and SSID",         G_CALLBACK(wlan_prepare_filter_and_not_selected_BSSID_and_SSID_cb)},
1439   { "/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " and not Selected/BSSID or SSID",    NULL, "BSSID or SSID",  NULL, "BSSID or SSID",          G_CALLBACK(wlan_prepare_filter_and_not_selected_BSSID_or_SSID_cb)},
1440
1441   /* /Prepare a Filter/... or not Selected */
1442   { "/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " or not Selected/BSSID",                     NULL, "BSSID",                  NULL, "BSSID",                          G_CALLBACK(wlan_prepare_filter_or_not_selected_BSSID_cb)},
1443   { "/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " or not Selected/SSID",                      NULL, "SSID",                   NULL, "SSID",                           G_CALLBACK(wlan_prepare_filter_or_not_selected_SSID_cb)},
1444   { "/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " or not Selected/BSSID and SSID",    NULL, "BSSID and SSID", NULL, "BSSID and SSID",         G_CALLBACK(wlan_prepare_filter_or_not_selected_BSSID_and_SSID_cb)},
1445   { "/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " or not Selected/BSSID or SSID",     NULL, "BSSID or SSID",  NULL, "BSSID or SSID",          G_CALLBACK(wlan_prepare_filter_or_not_selected_BSSID_or_SSID_cb)},
1446
1447   /* Find Frame*/
1448   { "/Find Frame/Find Frame",                                   NULL, "Find Frame",             NULL, NULL, NULL },
1449   { "/Find Frame/Find Next",                                    NULL, "Find Next",              NULL, NULL, NULL },
1450   { "/Find Frame/Find Previous",                                NULL, "Find Previous",  NULL, NULL, NULL },
1451
1452   /* Find Frame/Find Frame*/
1453   { "/Find Frame/Find Frame/BSSID",                             NULL, "BSSID",                  NULL, "BSSID",                          G_CALLBACK(wlan_find_frame_BSSID_cb)},
1454   { "/Find Frame/Find Frame/SSID",                              NULL, "SSID",                   NULL, "SSID",                           G_CALLBACK(wlan_find_frame_SSID_cb)},
1455   { "/Find Frame/Find Frame/BSSID and SSID",    NULL, "SSID and SSID",  NULL, "SSID and SSID",          G_CALLBACK(wlan_find_frame_BSSID_and_SSID_cb)},
1456   { "/Find Frame/Find Frame/BSSID or SSID",             NULL, "BSSID",                  NULL, "BSSID",                          G_CALLBACK(wlan_find_frame_BSSID_or_SSID_cb)},
1457
1458   /* Find Frame/Find Next*/
1459   { "/Find Frame/Find Next/BSSID",                              NULL, "BSSID",                  NULL, "BSSID",                          G_CALLBACK(wlan_find_frame_next_BSSID_cb)},
1460   { "/Find Frame/Find Next/SSID",                               NULL, "SSID",                   NULL, "SSID",                           G_CALLBACK(wlan_find_frame_next_SSID_cb)},
1461   { "/Find Frame/Find Next/BSSID and SSID",             NULL, "SSID and SSID",  NULL, "SSID and SSID",          G_CALLBACK(wlan_find_frame_next_BSSID_and_SSID_cb)},
1462   { "/Find Frame/Find Next/BSSID or SSID",              NULL, "BSSID",                  NULL, "BSSID",                          G_CALLBACK(wlan_find_frame_next_BSSID_or_SSID_cb)},
1463
1464   /* Find Frame/Find Previous*/
1465   { "/Find Frame/Find Previous/BSSID",                          NULL, "BSSID",                  NULL, "BSSID",                          G_CALLBACK(wlan_find_frame_previous_BSSID_cb)},
1466   { "/Find Frame/Find Previous/SSID",                           NULL, "SSID",                   NULL, "SSID",                           G_CALLBACK(wlan_find_frame_previous_SSID_cb)},
1467   { "/Find Frame/Find Previous/BSSID and SSID",         NULL, "SSID and SSID",  NULL, "SSID and SSID",          G_CALLBACK(wlan_find_frame_previous_BSSID_and_SSID_cb)},
1468   { "/Find Frame/Find Previous/BSSID or SSID",          NULL, "BSSID",                  NULL, "BSSID",                          G_CALLBACK(wlan_find_frame_previous_BSSID_or_SSID_cb)},
1469
1470   /* Colorize */
1471   { "/Colorize/BSSID",                          NULL, "BSSID",                  NULL, "BSSID",                          G_CALLBACK(wlan_colorize_BSSID_cb)},
1472   { "/Colorize/SSID",                           NULL, "SSID",                   NULL, "SSID",                           G_CALLBACK(wlan_colorize_SSID_cb)},
1473   { "/Colorize/BSSID and SSID",         NULL, "BSSID and SSID", NULL, "BSSID and SSID",         G_CALLBACK(wlan_colorize_BSSID_and_SSID_cb)},
1474   { "/Colorize/BSSID or SSID",          NULL, "BSSID or SSID",  NULL, "BSSID or SSID",          G_CALLBACK(wlan_colorize_BSSID_or_SSID_cb)},
1475
1476 };
1477
1478 static void
1479 wlan_create_popup_menu(wlanstat_t *hs)
1480 {
1481         GtkUIManager *ui_manager;
1482         GtkActionGroup *action_group;
1483         GError *error = NULL;
1484
1485         action_group = gtk_action_group_new ("WlanFilterPopupActionGroup");
1486         gtk_action_group_add_actions (action_group,                                                     /* the action group */
1487                                                                 wlans_stat_popup_entries,                               /* an array of action descriptions */
1488                                                                 G_N_ELEMENTS(wlans_stat_popup_entries), /* the number of entries */
1489                                                                 hs);                                                                    /* data to pass to the action callbacks */
1490
1491         ui_manager = gtk_ui_manager_new ();
1492         gtk_ui_manager_insert_action_group (ui_manager, action_group, 0);
1493         gtk_ui_manager_add_ui_from_string (ui_manager,ui_desc_wlan_stat_filter_popup, -1, &error);
1494         if (error != NULL)
1495     {
1496         fprintf (stderr, "Warning: building Wlan Stat Filter popup failed: %s\n",
1497                 error->message);
1498         g_error_free (error);
1499         error = NULL;
1500     }
1501         hs->menu = gtk_ui_manager_get_widget(ui_manager, "/WlanStatFilterPopup");
1502         g_signal_connect(hs->table, "button_press_event", G_CALLBACK(wlan_show_popup_menu_cb), hs);
1503
1504 }
1505
1506 static gboolean
1507 wlan_details_show_popup_menu_cb(void *widg _U_, GdkEvent *event, wlanstat_t *et)
1508 {
1509         GdkEventButton *bevent = (GdkEventButton *)event;
1510         GtkTreeSelection *sel;
1511         GtkTreeModel *model;
1512         GtkTreeIter iter;
1513
1514         /* To qoute the "Gdk Event Structures" doc:
1515          * "Normally button 1 is the left mouse button, 2 is the middle button, and 3 is the right button" */
1516         if(event->type==GDK_BUTTON_PRESS && bevent->button==3){
1517                 /* if this is a right click on one of our columns, popup the context menu */
1518                 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW(et->details));
1519                 if (gtk_tree_selection_get_selected (sel, &model, &iter)) {
1520                         gtk_menu_popup(GTK_MENU(et->details_menu), NULL, NULL, NULL, NULL,
1521                                        bevent->button, bevent->time);
1522                 }
1523         }
1524
1525         return FALSE;
1526 }
1527
1528 /* Apply as Filter/ */
1529
1530 static void
1531 wlan_details_apply_selected_cb(GtkWidget *widget, gpointer user_data)
1532 {
1533         wlan_details_select_filter_cb( widget , user_data, CALLBACK_MATCH(ACTYPE_SELECTED, 0));
1534 }
1535
1536 static void
1537 wlan_details_apply_not_selected_cb(GtkWidget *widget, gpointer user_data)
1538 {
1539         wlan_details_select_filter_cb( widget , user_data, CALLBACK_MATCH(ACTYPE_NOT_SELECTED, 0));
1540 }
1541
1542 static void
1543 wlan_details_apply_and_selected_cb(GtkWidget *widget, gpointer user_data)
1544 {
1545         wlan_details_select_filter_cb( widget , user_data, CALLBACK_MATCH(ACTYPE_AND_SELECTED, 0));
1546 }
1547
1548 static void
1549 wlan_details_apply_or_selected_cb(GtkWidget *widget, gpointer user_data)
1550 {
1551         wlan_details_select_filter_cb( widget , user_data, CALLBACK_MATCH(ACTYPE_OR_SELECTED, 0));
1552 }
1553
1554 static void
1555 wlan_details_apply_and_not_selected_cb(GtkWidget *widget, gpointer user_data)
1556 {
1557         wlan_details_select_filter_cb( widget , user_data, CALLBACK_MATCH(ACTYPE_AND_NOT_SELECTED, 0));
1558 }
1559
1560 static void
1561 wlan_details_apply_or_not_selected_cb(GtkWidget *widget, gpointer user_data)
1562 {
1563         wlan_details_select_filter_cb( widget , user_data, CALLBACK_MATCH(ACTYPE_OR_NOT_SELECTED, 0));
1564 }
1565 /* Prepare a filter */
1566 static void
1567 wlan_details_prepare_selected_cb(GtkWidget *widget, gpointer user_data)
1568 {
1569         wlan_details_select_filter_cb( widget , user_data, CALLBACK_PREPARE(ACTYPE_SELECTED, 0));
1570 }
1571
1572 static void
1573 wlan_details_prepare_not_selected_cb(GtkWidget *widget, gpointer user_data)
1574 {
1575         wlan_details_select_filter_cb( widget , user_data, CALLBACK_PREPARE(ACTYPE_NOT_SELECTED, 0));
1576 }
1577
1578 static void
1579 wlan_details_prepare_and_selected_cb(GtkWidget *widget, gpointer user_data)
1580 {
1581         wlan_details_select_filter_cb( widget , user_data, CALLBACK_PREPARE(ACTYPE_AND_SELECTED, 0));
1582 }
1583
1584 static void
1585 wlan_details_prepare_or_selected_cb(GtkWidget *widget, gpointer user_data)
1586 {
1587         wlan_details_select_filter_cb( widget , user_data, CALLBACK_PREPARE(ACTYPE_OR_SELECTED, 0));
1588 }
1589
1590 static void
1591 wlan_details_prepare_and_not_selected_cb(GtkWidget *widget, gpointer user_data)
1592 {
1593         wlan_details_select_filter_cb( widget , user_data, CALLBACK_PREPARE(ACTYPE_AND_NOT_SELECTED, 0));
1594 }
1595
1596 static void
1597 wlan_details_prepare_or_not_selected_cb(GtkWidget *widget, gpointer user_data)
1598 {
1599         wlan_details_select_filter_cb( widget , user_data, CALLBACK_PREPARE(ACTYPE_OR_NOT_SELECTED, 0));
1600 }
1601
1602 static void
1603 wlan_details_find_frame_cb(GtkWidget *widget, gpointer user_data)
1604 {
1605         wlan_details_select_filter_cb( widget , user_data, CALLBACK_FIND_FRAME(ACTYPE_SELECTED, 0));
1606 }
1607 static void
1608 wlan_details_find_next_frame_cb(GtkWidget *widget, gpointer user_data)
1609 {
1610         wlan_details_select_filter_cb( widget , user_data, CALLBACK_FIND_FRAME(ACTYPE_OR_NOT_SELECTED, 0));
1611 }
1612 static void
1613 wlan_details_find_previous_frame_cb(GtkWidget *widget, gpointer user_data)
1614 {
1615         wlan_details_select_filter_cb( widget , user_data, CALLBACK_FIND_FRAME(ACTYPE_OR_NOT_SELECTED, 0));
1616 }
1617
1618
1619 static const char *ui_desc_wlan_details_filter_popup =
1620 "<ui>\n"
1621 "  <popup name='WlanStatFilterPopup' action='PopupAction'>\n"
1622 "    <menu name= 'ApplyAsFilter' action='/Apply as Filter'>\n"
1623 "        <menuitem action='/Apply as Filter/Selected'/>\n"
1624 "        <menuitem action='/Apply as Filter/Not Selected'/>\n"
1625 "        <menuitem action='/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " and Selected'/>\n"
1626 "        <menuitem action='/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " or Selected'/>\n"
1627 "        <menuitem action='/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " and not Selected'/>\n"
1628 "        <menuitem action='/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " or not Selected'/>\n"
1629 "    </menu>\n"
1630 "    <menu name= 'PrepareAFilter' action='/Prepare a Filter'>\n"
1631 "        <menuitem action='/Prepare a Filter/Selected'/>\n"
1632 "        <menuitem action='/Prepare a Filter/Not Selected'/>\n"
1633 "        <menuitem action='/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " and Selected'/>\n"
1634 "        <menuitem action='/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " or Selected'/>\n"
1635 "        <menuitem action='/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " and not Selected'/>\n"
1636 "        <menuitem action='/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " or not Selected'/>\n"
1637 "    </menu>\n"
1638 "    <menu name= 'FindFrame' action='/Find Frame'>\n"
1639 "        <menuitem action='/Find Frame/Find Frame'/>\n"
1640 "        <menuitem action='/Find Frame/Find Next'/>\n"
1641 "        <menuitem action='/Find Frame/Find Previous'/>\n"
1642 "    </menu>\n"
1643 "  </popup>\n"
1644 "</ui>\n";
1645
1646 /*
1647  * GtkActionEntry
1648  * typedef struct {
1649  *   const gchar     *name;
1650  *   const gchar     *stock_id;
1651  *   const gchar     *label;
1652  *   const gchar     *accelerator;
1653  *   const gchar     *tooltip;
1654  *   GCallback  callback;
1655  * } GtkActionEntry;
1656  * const gchar *name;                   The name of the action.
1657  * const gchar *stock_id;               The stock id for the action, or the name of an icon from the icon theme.
1658  * const gchar *label;                  The label for the action. This field should typically be marked for translation,
1659  *                                                              see gtk_action_group_set_translation_domain().
1660  *                                                              If label is NULL, the label of the stock item with id stock_id is used.
1661  * const gchar *accelerator;    The accelerator for the action, in the format understood by gtk_accelerator_parse().
1662  * const gchar *tooltip;                The tooltip for the action. This field should typically be marked for translation,
1663  *                              see gtk_action_group_set_translation_domain().
1664  * GCallback callback;                  The function to call when the action is activated.
1665  *
1666  */
1667 static const GtkActionEntry wlan_details_list_popup_entries[] = {
1668   /* Top level */
1669   { "/Apply as Filter",                                                 NULL, "Apply as Filter", NULL, NULL, NULL },
1670   { "/Prepare a Filter",                                                NULL, "Prepare a Filter", NULL, NULL, NULL },
1671   { "/Find Frame",                                                              NULL, "Find Frame", NULL, NULL, NULL },
1672
1673     /* Apply as */
1674   { "/Apply as Filter/Selected",                                NULL, "Selected" ,                              NULL, NULL, G_CALLBACK(wlan_details_apply_selected_cb) },
1675   { "/Apply as Filter/Not Selected",                    NULL, "Not Selected",                   NULL, NULL, G_CALLBACK(wlan_details_apply_not_selected_cb) },
1676   { "/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " and Selected",               NULL, UTF8_HORIZONTAL_ELLIPSIS " and Selected",         NULL, NULL, G_CALLBACK(wlan_details_apply_and_selected_cb) },
1677   { "/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " or Selected",                        NULL, UTF8_HORIZONTAL_ELLIPSIS " or Selected",          NULL, NULL, G_CALLBACK(wlan_details_apply_or_selected_cb) },
1678   { "/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " and not Selected",   NULL, UTF8_HORIZONTAL_ELLIPSIS " and not Selected",     NULL, NULL, G_CALLBACK(wlan_details_apply_and_not_selected_cb) },
1679   { "/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS " or not Selected",            NULL, UTF8_HORIZONTAL_ELLIPSIS " or not Selected",      NULL, NULL, G_CALLBACK(wlan_details_apply_or_not_selected_cb) },
1680
1681   { "/Prepare a Filter/Selected",                               NULL, "Selected" ,                              NULL, NULL, G_CALLBACK(wlan_details_prepare_selected_cb) },
1682   { "/Prepare a Filter/Not Selected",                   NULL, "Not Selected",                   NULL, NULL, G_CALLBACK(wlan_details_prepare_not_selected_cb) },
1683   { "/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " and Selected",              NULL, UTF8_HORIZONTAL_ELLIPSIS " and Selected",         NULL, NULL, G_CALLBACK(wlan_details_prepare_and_selected_cb) },
1684   { "/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " or Selected",               NULL, UTF8_HORIZONTAL_ELLIPSIS " or Selected",          NULL, NULL, G_CALLBACK(wlan_details_prepare_or_selected_cb) },
1685   { "/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " and not Selected",  NULL, UTF8_HORIZONTAL_ELLIPSIS " and not Selected",     NULL, NULL, G_CALLBACK(wlan_details_prepare_and_not_selected_cb) },
1686   { "/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS " or not Selected",   NULL, UTF8_HORIZONTAL_ELLIPSIS " or not Selected",      NULL, NULL, G_CALLBACK(wlan_details_prepare_or_not_selected_cb) },
1687
1688   /* Find Frame*/
1689   { "/Find Frame/Find Frame",                                   NULL, "Find Frame",                             NULL, NULL, G_CALLBACK(wlan_details_find_frame_cb) },
1690   { "/Find Frame/Find Next",                                    NULL, "Find Next",                              NULL, NULL, G_CALLBACK(wlan_details_find_next_frame_cb) },
1691   { "/Find Frame/Find Previous",                                NULL, "Find Previous",                  NULL, NULL, G_CALLBACK(wlan_details_find_previous_frame_cb) },
1692
1693 };
1694
1695 static void
1696 wlan_details_create_popup_menu(wlanstat_t *hs)
1697 {
1698         GtkUIManager *ui_manager;
1699         GtkActionGroup *action_group;
1700         GError *error = NULL;
1701
1702         action_group = gtk_action_group_new ("WlanDetailsPopupActionGroup");
1703         gtk_action_group_add_actions (action_group,                                                                     /* the action group */
1704                                                                 wlan_details_list_popup_entries,                                /* an array of action descriptions */
1705                                                                 G_N_ELEMENTS(wlan_details_list_popup_entries),  /* the number of entries */
1706                                                                 hs);                                                                                    /* data to pass to the action callbacks */
1707
1708         ui_manager = gtk_ui_manager_new ();
1709         gtk_ui_manager_insert_action_group (ui_manager, action_group, 0);
1710         gtk_ui_manager_add_ui_from_string (ui_manager,ui_desc_wlan_details_filter_popup, -1, &error);
1711         if (error != NULL)
1712     {
1713         fprintf (stderr, "Warning: building Wlan details list popup failed: %s\n",
1714                 error->message);
1715         g_error_free (error);
1716         error = NULL;
1717     }
1718         hs->details_menu = gtk_ui_manager_get_widget(ui_manager, "/WlanStatFilterPopup");
1719         g_signal_connect(hs->details, "button_press_event", G_CALLBACK(wlan_details_show_popup_menu_cb), hs);
1720
1721 }
1722
1723 static void
1724 wlanstat_dlg_create (void)
1725 {
1726         wlanstat_t    *hs;
1727         GString       *error_string;
1728         GtkWidget     *scrolled_window;
1729         GtkWidget     *bbox;
1730         GtkWidget     *vbox;
1731         GtkWidget     *hbox;
1732         GtkWidget     *frame;
1733         GtkWidget     *selected_vb;
1734         GtkWidget     *resolv_cb;
1735         GtkWidget     *filter_cb;
1736         GtkWidget     *existing_cb;
1737         GtkWidget     *close_bt;
1738         GtkWidget     *help_bt;
1739         GtkWidget     *copy_bt;
1740         GtkTooltips   *tooltips = gtk_tooltips_new();
1741         GtkListStore  *store;
1742         GtkTreeView       *tree_view;
1743         GtkCellRenderer   *renderer;
1744         GtkTreeViewColumn *column;
1745         GtkTreeSelection  *sel;
1746         char title[256];
1747         gint i;
1748
1749         hs=g_malloc (sizeof(wlanstat_t));
1750         hs->num_entries = 0;
1751         hs->ep_list = NULL;
1752         hs->number_of_packets = 0;
1753         hs->resolve_names = TRUE;
1754         hs->use_dfilter = FALSE;
1755         hs->show_only_existing = FALSE;
1756
1757         g_snprintf (title, sizeof(title), "Wireshark: WLAN Traffic Statistics: %s",
1758                     cf_get_display_name(&cfile));
1759         wlanstat_dlg_w = window_new_with_geom (GTK_WINDOW_TOPLEVEL, title, "WLAN Statistics");
1760         gtk_window_set_default_size (GTK_WINDOW(wlanstat_dlg_w), 750, 400);
1761
1762         vbox=gtk_vbox_new (FALSE, 3);
1763         gtk_container_add(GTK_CONTAINER(wlanstat_dlg_w), vbox);
1764         gtk_container_set_border_width (GTK_CONTAINER(vbox), 6);
1765
1766         wlanstat_pane = gtk_vpaned_new();
1767         gtk_box_pack_start (GTK_BOX (vbox), wlanstat_pane, TRUE, TRUE, 0);
1768         gtk_paned_set_position(GTK_PANED(wlanstat_pane), recent.gui_geometry_wlan_stats_pane);
1769         gtk_widget_show(wlanstat_pane);
1770
1771         /* init a scrolled window for overview */
1772         wlanstat_name_lb = gtk_frame_new("Network Overview");
1773         gtk_paned_pack1(GTK_PANED(wlanstat_pane), wlanstat_name_lb, FALSE, TRUE);
1774         selected_vb = gtk_vbox_new(FALSE, 0);
1775         gtk_container_add(GTK_CONTAINER(wlanstat_name_lb), selected_vb);
1776         gtk_container_set_border_width(GTK_CONTAINER(selected_vb), 5);
1777
1778         scrolled_window = scrolled_window_new (NULL, NULL);
1779         gtk_box_pack_start(GTK_BOX(selected_vb), scrolled_window, TRUE, TRUE, 0);
1780         gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled_window),
1781                                             GTK_SHADOW_IN);
1782
1783         store = gtk_list_store_new(NUM_COLUMNS, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
1784                                    G_TYPE_STRING, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT,
1785                                    G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT,
1786                                    G_TYPE_STRING, G_TYPE_FLOAT, G_TYPE_POINTER);
1787         hs->table = GTK_TREE_VIEW(tree_view_new(GTK_TREE_MODEL(store)));
1788         gtk_container_add(GTK_CONTAINER (scrolled_window), GTK_WIDGET(hs->table));
1789         g_object_unref(G_OBJECT(store));
1790
1791         tree_view = hs->table;
1792         gtk_tree_view_set_headers_visible(tree_view, TRUE);
1793         gtk_tree_view_set_headers_clickable(tree_view, TRUE);
1794
1795         for (i = 0; i <= PROTECTION_COLUMN; i++) {
1796 #if GTK_CHECK_VERSION(2,6,0)
1797                 if (i == PERCENT_COLUMN) {
1798                         renderer = gtk_cell_renderer_progress_new();
1799                         column = gtk_tree_view_column_new_with_attributes(titles[i], renderer,
1800                                                                           "text", i,
1801                                                                           "value", PERCENT_VALUE_COLUMN,
1802                                                                           NULL);
1803                         gtk_tree_view_column_set_expand(column, TRUE);
1804                         gtk_tree_view_column_set_sort_column_id(column, PERCENT_VALUE_COLUMN);
1805                 } else {
1806 #else
1807                 {
1808 #endif
1809                         renderer = gtk_cell_renderer_text_new();
1810                         column = gtk_tree_view_column_new_with_attributes(titles[i], renderer,
1811                                                                           "text", i,
1812                                                                           NULL);
1813                         gtk_tree_view_column_set_sort_column_id(column, i);
1814                 }
1815
1816                 if (i != BSSID_COLUMN && i != SSID_COLUMN && i != PROTECTION_COLUMN) {
1817                         /* Align all number columns */
1818                         g_object_set(G_OBJECT(renderer), "xalign", 1.0, NULL);
1819                 }
1820                 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
1821                 gtk_tree_view_column_set_resizable(column, TRUE);
1822                 gtk_tree_view_append_column(tree_view, column);
1823
1824                 if (i == SSID_COLUMN) {
1825                         /* Sort the SSID column */
1826                         gtk_tree_view_column_clicked(column);
1827                 }
1828         }
1829
1830         sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(hs->table));
1831         gtk_tree_selection_set_mode(sel, GTK_SELECTION_SINGLE);
1832         g_signal_connect(sel, "changed", G_CALLBACK(wlan_select_cb), hs);
1833
1834         /* init a scrolled window for details */
1835         frame = gtk_frame_new("Selected Network");
1836         gtk_paned_pack2(GTK_PANED(wlanstat_pane), frame, FALSE, TRUE);
1837         selected_vb = gtk_vbox_new(FALSE, 0);
1838         gtk_container_add(GTK_CONTAINER(frame), selected_vb);
1839         gtk_container_set_border_width(GTK_CONTAINER(selected_vb), 5);
1840
1841         scrolled_window = scrolled_window_new (NULL, NULL);
1842         gtk_box_pack_start(GTK_BOX(selected_vb), scrolled_window, TRUE, TRUE, 0);
1843         gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled_window),
1844                                             GTK_SHADOW_IN);
1845
1846         store = gtk_list_store_new(NUM_DETAIL_COLUMNS, G_TYPE_STRING, G_TYPE_STRING,
1847                                    G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT,
1848                                    G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, G_TYPE_STRING,
1849                                    G_TYPE_FLOAT, G_TYPE_POINTER);
1850         hs->details = GTK_TREE_VIEW(tree_view_new(GTK_TREE_MODEL(store)));
1851         gtk_container_add(GTK_CONTAINER (scrolled_window), GTK_WIDGET(hs->details));
1852         g_object_unref(G_OBJECT(store));
1853
1854         tree_view = hs->details;
1855         gtk_tree_view_set_headers_visible(tree_view, TRUE);
1856         gtk_tree_view_set_headers_clickable(tree_view, TRUE);
1857
1858         for (i = 0; i <= COMMENT_COLUMN; i++) {
1859 #if GTK_CHECK_VERSION(2,6,0)
1860                 if (i == PERCENT_2_COLUMN) {
1861                         renderer = gtk_cell_renderer_progress_new();
1862                         column = gtk_tree_view_column_new_with_attributes(detail_titles[i], renderer,
1863                                                                           "text", i,
1864                                                                           "value", PERCENT_VALUE_2_COLUMN,
1865                                                                           NULL);
1866                         gtk_tree_view_column_set_expand(column, TRUE);
1867                         gtk_tree_view_column_set_sort_column_id(column, PERCENT_VALUE_2_COLUMN);
1868                 } else {
1869 #else
1870                 {
1871 #endif
1872                         renderer = gtk_cell_renderer_text_new();
1873                         column = gtk_tree_view_column_new_with_attributes(detail_titles[i], renderer,
1874                                                                           "text", i,
1875                                                                           NULL);
1876                         gtk_tree_view_column_set_sort_column_id(column, i);
1877                 }
1878
1879                 if (i != ADDRESS_COLUMN && i != COMMENT_COLUMN) {
1880                         /* Align all number columns */
1881                         g_object_set(G_OBJECT(renderer), "xalign", 1.0, NULL);
1882                 }
1883                 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
1884                 gtk_tree_view_column_set_resizable(column, TRUE);
1885                 gtk_tree_view_append_column(tree_view, column);
1886
1887                 if (i == ADDRESS_COLUMN) {
1888                         /* Sort the Address column */
1889                         gtk_tree_view_column_clicked(column);
1890                 }
1891         }
1892
1893         sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(hs->table));
1894         gtk_tree_selection_set_mode(sel, GTK_SELECTION_SINGLE);
1895
1896         /* create popup menu for this table */
1897         wlan_create_popup_menu(hs);
1898         wlan_details_create_popup_menu(hs);
1899
1900         error_string=register_tap_listener ("wlan", hs, NULL, 0,
1901                                             wlanstat_reset, wlanstat_packet,
1902                                             wlanstat_draw);
1903         if (error_string) {
1904                 simple_dialog (ESD_TYPE_ERROR, ESD_BTN_OK, "%s", error_string->str);
1905                 g_string_free (error_string, TRUE);
1906                 g_free (hs);
1907                 return;
1908         }
1909
1910         hbox = gtk_hbox_new(FALSE, 3);
1911         gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
1912
1913         resolv_cb = gtk_check_button_new_with_mnemonic("Name resolution");
1914         gtk_container_add(GTK_CONTAINER(hbox), resolv_cb);
1915         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(resolv_cb), TRUE);
1916         gtk_tooltips_set_tip(tooltips, resolv_cb, "Show results of name resolutions rather than the \"raw\" values. "
1917                              "Please note: The corresponding name resolution must be enabled.", NULL);
1918
1919         g_signal_connect(resolv_cb, "toggled", G_CALLBACK(wlan_resolve_toggle_dest), hs);
1920
1921         filter_cb = gtk_check_button_new_with_mnemonic("Limit to display filter");
1922         gtk_container_add(GTK_CONTAINER(hbox), filter_cb);
1923         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(filter_cb), FALSE);
1924         gtk_tooltips_set_tip(tooltips, filter_cb, "Limit the list to entries matching the current display filter.", NULL);
1925         g_signal_connect(filter_cb, "toggled", G_CALLBACK(wlan_filter_toggle_dest), hs);
1926
1927         existing_cb = gtk_check_button_new_with_mnemonic("Only show existing networks");
1928         gtk_container_add(GTK_CONTAINER(hbox), existing_cb);
1929         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(existing_cb), FALSE);
1930         gtk_tooltips_set_tip(tooltips, existing_cb, "This option disables probe requests for "
1931                              "unknown networks.", NULL);
1932         g_signal_connect(existing_cb, "toggled", G_CALLBACK(wlan_existing_toggle_dest), hs);
1933
1934         /* Button row. */
1935         bbox = dlg_button_row_new (GTK_STOCK_CLOSE, GTK_STOCK_COPY, GTK_STOCK_HELP, NULL);
1936
1937         gtk_box_pack_end (GTK_BOX(vbox), bbox, FALSE, FALSE, 0);
1938
1939         close_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_CLOSE);
1940         window_set_cancel_button (wlanstat_dlg_w, close_bt, window_cancel_button_cb);
1941
1942         copy_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_COPY);
1943 /*      gtk_button_set_label(GTK_BUTTON(copy_bt), "Copy Overview"); */
1944         gtk_tooltips_set_tip(tooltips, copy_bt,
1945                              "Copy all statistical values of this page to the clipboard in CSV (Comma Separated Values) format.", NULL);
1946         g_signal_connect(copy_bt, "clicked", G_CALLBACK(wlan_copy_as_csv), hs->table);
1947
1948         help_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_HELP);
1949         g_signal_connect(help_bt, "clicked", G_CALLBACK(topic_cb), (gpointer)HELP_STATS_WLAN_TRAFFIC_DIALOG);
1950
1951         g_signal_connect (wlanstat_dlg_w, "delete_event", G_CALLBACK(window_delete_event_cb), NULL);
1952         g_signal_connect (wlanstat_dlg_w, "destroy", G_CALLBACK(win_destroy_cb), hs);
1953
1954         gtk_widget_show_all (wlanstat_dlg_w);
1955         window_present (wlanstat_dlg_w);
1956
1957         cf_retap_packets (&cfile);
1958         gdk_window_raise(wlanstat_dlg_w->window);
1959 }
1960
1961 static void
1962 wlanstat_launch (GtkWidget *w _U_, gpointer data _U_)
1963 {
1964         if (wlanstat_dlg_w) {
1965                 reactivate_window(wlanstat_dlg_w);
1966         } else {
1967                 wlanstat_dlg_create ();
1968         }
1969 }
1970
1971 void
1972 register_tap_listener_wlanstat (void)
1973 {
1974         static const char src[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
1975
1976         SET_ADDRESS(&broadcast, AT_ETHER, 6, src);
1977
1978         register_stat_menu_item ("WLAN Traffic", REGISTER_STAT_GROUP_UNSORTED,
1979                                  wlanstat_launch, NULL, NULL, NULL);
1980 }