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