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