20af498e74a53c59204d6653d8b64f35dc2c4092
[obnox/wireshark/wip.git] / gtk / main_menu.c
1 /* main_menu.c
2  * Main menu routines
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 #ifdef HAVE_CONFIG_H
26 # include "config.h"
27 #endif
28
29 #include <gtk/gtk.h>
30
31 #include <string.h>
32
33 #include <epan/packet.h>
34 #include <epan/addr_resolv.h>
35 #include <epan/prefs.h>
36 #include <epan/prefs-int.h>
37 #include <epan/tap.h>
38 #include <epan/timestamp.h>
39 #include <epan/etypes.h>
40 #include <epan/ipproto.h>
41 #include <epan/dissector_filters.h>
42 #include <epan/strutil.h>
43 #include <epan/plugins.h>
44 #include <epan/epan_dissect.h>
45
46 #include "../print.h"
47 #include "../register.h"
48 #include "../ui_util.h"
49 #include "../simple_dialog.h"
50 #include "../color_filters.h"
51 #include "../stat_menu.h"
52
53 #include "gtk/about_dlg.h"
54 #include "gtk/capture_dlg.h"
55 #include "gtk/capture_if_dlg.h"
56 #include "gtk/color_dlg.h"
57 #include "gtk/filter_dlg.h"
58 #include "gtk/profile_dlg.h"
59 #include "gtk/dlg_utils.h"
60 #include "gtk/capture_file_dlg.h"
61 #include "gtk/fileset_dlg.h"
62 #include "gtk/find_dlg.h"
63 #include "gtk/goto_dlg.h"
64 #include "gtk/summary_dlg.h"
65 #include "gtk/prefs_dlg.h"
66 #include "gtk/packet_win.h"
67 #include "gtk/follow_tcp.h"
68 #include "gtk/follow_udp.h"
69 #include "gtk/follow_ssl.h"
70 #include "gtk/decode_as_dlg.h"
71 #include "gtk/help_dlg.h"
72 #include "gtk/supported_protos_dlg.h"
73 #include "gtk/proto_dlg.h"
74 #include "gtk/proto_hier_stats_dlg.h"
75 #include "gtk/keys.h"
76 #include "gtk/stock_icons.h"
77 #include "gtk/gtkglobals.h"
78 #include "gtk/recent.h"
79 #include "gtk/main_proto_draw.h"
80 #include "gtk/conversations_table.h"
81 #include "gtk/hostlist_table.h"
82 #include "gtk/packet_history.h"
83 #include "gtk/sctp_stat.h"
84 #include "gtk/firewall_dlg.h"
85 #include "gtk/u3.h"
86 #include "gtk/macros_dlg.h"
87 #include "gtk/export_object.h"
88 #include "gtk/gui_stat_menu.h"
89 #include "gtk/main.h"
90 #include "gtk/main_menu.h"
91 #include "gtk/main_packet_list.h"
92 #include "gtk/main_toolbar.h"
93 #include "gtk/main_welcome.h"
94 #include "gtk/uat_gui.h"
95
96 #ifdef HAVE_IGE_MAC_INTEGRATION
97 #include <ige-mac-menu.h>
98 #endif
99
100 typedef struct _menu_item {
101     char    *name;
102     gint    group;
103     const char *stock_id;
104     gboolean enabled;
105     GtkItemFactoryCallback callback;
106     gpointer callback_data;
107     gboolean (*selected_packet_enabled)(frame_data *, epan_dissect_t *, gpointer callback_data);
108     gboolean (*selected_tree_row_enabled)(field_info *, gpointer callback_data);
109     GList *children;
110 } menu_item_t;
111
112 static GList *tap_menu_tree_root = NULL;
113
114 GtkWidget *popup_menu_object;
115
116
117 #define GTK_MENU_FUNC(a) ((GtkItemFactoryCallback)(a))
118
119 static void merge_all_tap_menus(GList *node);
120 static void clear_menu_recent_capture_file_cmd_cb(GtkWidget *w, gpointer unused _U_);
121
122 static void menus_init(void);
123 static void set_menu_sensitivity (GtkItemFactory *, const gchar *, gint);
124 static void show_hide_cb(GtkWidget *w, gpointer data, gint action);
125 static void timestamp_format_cb(GtkWidget *w, gpointer d, gint action);
126 static void timestamp_precision_cb(GtkWidget *w, gpointer d, gint action);
127 static void name_resolution_cb(GtkWidget *w, gpointer d, gint action);
128 #ifdef HAVE_LIBPCAP
129 static void auto_scroll_live_cb(GtkWidget *w, gpointer d);
130 #endif
131 static void colorize_cb(GtkWidget *w, gpointer d);
132
133
134 /* This is the GtkItemFactoryEntry structure used to generate new menus.
135        Item 1: The menu path. The letter after the underscore indicates an
136                accelerator key once the menu is open.
137        Item 2: The accelerator key for the entry
138        Item 3: The callback function.
139        Item 4: The callback action.  This changes the parameters with
140                which the function is called.  The default is 0.
141        Item 5: The item type, used to define what kind of an item it is.
142                Here are the possible values:
143
144                NULL               -> "<Item>"
145                ""                 -> "<Item>"
146                "<Title>"          -> create a title item
147                "<Item>"           -> create a simple item
148                "<ImageItem>"      -> create an item holding an image (gtk2)
149                "<StockItem>"      -> create an item holding a stock image (gtk2)
150                "<CheckItem>"      -> create a check item
151                "<ToggleItem>"     -> create a toggle item
152                "<RadioItem>"      -> create a radio item
153                <path>             -> path of a radio item to link against
154                "<Separator>"      -> create a separator
155                "<Tearoff>"        -> create a tearoff separator (gtk2)
156                "<Branch>"         -> create an item to hold sub items (optional)
157                "<LastBranch>"     -> create a right justified branch
158        Item 6: extra data needed for ImageItem and StockItem (gtk2)
159     */
160
161 /*  As a general GUI guideline, we try to follow the Gnome Human Interface Guidelines, which can be found at:
162     http://developer.gnome.org/projects/gup/hig/1.0/index.html
163
164 Please note: there are some differences between the Gnome HIG menu suggestions and our implementation:
165
166 File/Open Recent:   the Gnome HIG suggests putting the list of recently used files as elements into the File menuitem.
167                     As this is ok for only a few items, this will become unhandy for 10 or even more list entries.
168                     For this reason, we use a submenu for this.
169
170 File/Close:         the Gnome HIG suggests putting this item just above the Quit item.
171                     This results in unintuitive behaviour as both Close and Quit items are very near together.
172                     By putting the Close item near the open item(s), it better suggests that it will close the
173                     currently opened/captured file only.
174 */
175
176 typedef enum {
177     SHOW_HIDE_MAIN_TOOLBAR = 1,
178     SHOW_HIDE_FILTER_TOOLBAR,
179     SHOW_HIDE_AIRPCAP_TOOLBAR,
180     SHOW_HIDE_STATUSBAR,
181     SHOW_HIDE_PACKET_LIST,
182     SHOW_HIDE_TREE_VIEW,
183     SHOW_HIDE_BYTE_VIEW
184 } show_hide_values_e;
185
186 typedef enum {
187     CONV_ETHER = 1,
188     CONV_IP,
189     CONV_TCP,
190     CONV_UDP,
191     CONV_CBA
192 } conv_values_e;
193
194 static char *
195 build_conversation_filter(int action, gboolean show_dialog)
196 {
197     packet_info *pi = &cfile.edt->pi;
198     char        *buf;
199
200
201     switch(action) {
202     case(CONV_CBA):
203         if (pi->profinet_type == 0) {
204             if (show_dialog) {
205                 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
206                     "Error filtering conversation.  Please make\n"
207                     "sure you have a PROFINET CBA packet selected.");
208             }
209             return NULL;
210         }
211
212         if( pi->net_src.type == AT_IPv4 && pi->net_dst.type == AT_IPv4
213         && pi->ipproto == IP_PROTO_TCP ) {
214             /* IPv4 */
215             switch(pi->profinet_type) {
216             case(1):
217                 buf = g_strdup_printf("(ip.src eq %s and ip.dst eq %s and cba.acco.dcom == 1) || (ip.src eq %s and ip.dst eq %s and cba.acco.dcom == 0)",
218                     ip_to_str( pi->net_dst.data),
219                     ip_to_str( pi->net_src.data),
220                     ip_to_str( pi->net_src.data),
221                     ip_to_str( pi->net_dst.data));
222                 break;
223             case(2):
224                 buf = g_strdup_printf("(ip.src eq %s and ip.dst eq %s and cba.acco.dcom == 1) || (ip.src eq %s and ip.dst eq %s and cba.acco.dcom == 0)",
225                     ip_to_str( pi->net_src.data),
226                     ip_to_str( pi->net_dst.data),
227                     ip_to_str( pi->net_dst.data),
228                     ip_to_str( pi->net_src.data));
229                 break;
230             case(3):
231                 buf = g_strdup_printf("(ip.src eq %s and ip.dst eq %s and cba.acco.srt == 1) || (ip.src eq %s and ip.dst eq %s and cba.acco.srt == 0)",
232                     ip_to_str( pi->net_dst.data),
233                     ip_to_str( pi->net_src.data),
234                     ip_to_str( pi->net_src.data),
235                     ip_to_str( pi->net_dst.data));
236                 break;
237             case(4):
238                 buf = g_strdup_printf("(ip.src eq %s and ip.dst eq %s and cba.acco.srt == 1) || (ip.src eq %s and ip.dst eq %s and cba.acco.srt == 0)",
239                     ip_to_str( pi->net_src.data),
240                     ip_to_str( pi->net_dst.data),
241                     ip_to_str( pi->net_dst.data),
242                     ip_to_str( pi->net_src.data));
243                 break;
244             default:
245                 return NULL;
246             }
247         } else {
248             return NULL;
249         }
250         break;
251     case(CONV_TCP):
252         if (pi->ipproto != IP_PROTO_TCP) {
253             if (show_dialog) {
254                 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
255                     "Error filtering conversation.  Please make\n"
256                     "sure you have a TCP packet selected.");
257             }
258             return NULL;
259         }
260
261         if( pi->net_src.type == AT_IPv4 && pi->net_dst.type == AT_IPv4 ) {
262             /* TCP over IPv4 */
263             buf = g_strdup_printf("(ip.addr eq %s and ip.addr eq %s) and (tcp.port eq %d and tcp.port eq %d)",
264                 ip_to_str( pi->net_src.data),
265                 ip_to_str( pi->net_dst.data),
266                 pi->srcport, pi->destport );
267         } else if( pi->net_src.type == AT_IPv6 && pi->net_dst.type == AT_IPv6 ) {
268             /* TCP over IPv6 */
269             buf = g_strdup_printf("(ipv6.addr eq %s and ipv6.addr eq %s) and (tcp.port eq %d and tcp.port eq %d)",
270                 ip6_to_str((const struct e_in6_addr *)pi->net_src.data),
271                 ip6_to_str((const struct e_in6_addr *)pi->net_dst.data),
272                 pi->srcport, pi->destport );
273         } else {
274             return NULL;
275         }
276         break;
277     case(CONV_UDP):
278         if (pi->ipproto != IP_PROTO_UDP) {
279             if (show_dialog) {
280                 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
281                     "Error filtering conversation.  Please make\n"
282                     "sure you have a UDP packet selected.");
283             }
284             return NULL;
285         }
286
287         if( pi->net_src.type == AT_IPv4 && pi->net_dst.type == AT_IPv4 ) {
288             /* UDP over IPv4 */
289             buf = g_strdup_printf("(ip.addr eq %s and ip.addr eq %s) and (udp.port eq %d and udp.port eq %d)",
290                 ip_to_str( pi->net_src.data),
291                 ip_to_str( pi->net_dst.data),
292                 pi->srcport, pi->destport );
293         } else if( pi->net_src.type == AT_IPv6 && pi->net_dst.type == AT_IPv6 ) {
294             /* UDP over IPv6 */
295             buf = g_strdup_printf("(ipv6.addr eq %s and ipv6.addr eq %s) and (udp.port eq %d and udp.port eq %d)",
296                 ip6_to_str((const struct e_in6_addr *)pi->net_src.data),
297                 ip6_to_str((const struct e_in6_addr *)pi->net_dst.data),
298                 pi->srcport, pi->destport );
299         } else {
300             return NULL;
301         }
302         break;
303     case(CONV_IP):
304         if ((pi->ethertype != ETHERTYPE_IP) && (pi->ethertype != ETHERTYPE_IPv6)) {
305             if (show_dialog) {
306                 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
307                     "Error filtering conversation.  Please make\n"
308                     "sure you have a IP packet selected.");
309             }
310             return NULL;
311         }
312
313         if( pi->net_src.type == AT_IPv4 && pi->net_dst.type == AT_IPv4 ) {
314             /* IPv4 */
315             buf = g_strdup_printf("ip.addr eq %s and ip.addr eq %s",
316                 ip_to_str( pi->net_src.data),
317                 ip_to_str( pi->net_dst.data));
318         } else if( pi->net_src.type == AT_IPv6 && pi->net_dst.type == AT_IPv6 ) {
319             /* IPv6 */
320             buf = g_strdup_printf("ipv6.addr eq %s and ipv6.addr eq %s",
321                 ip6_to_str((const struct e_in6_addr *)pi->net_src.data),
322                 ip6_to_str((const struct e_in6_addr *)pi->net_dst.data));
323         } else {
324             return NULL;
325         }
326         break;
327     case(CONV_ETHER):
328         /* XXX - is this the right way to check for Ethernet? */
329         /* check for the data link address type */
330         /* (ethertype will be 0 when used as length field) */
331         if (pi->dl_src.type != AT_ETHER) {
332             if (show_dialog) {
333                 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
334                     "Error filtering conversation.  Please make\n"
335                     "sure you have a Ethernet packet selected.");
336             }
337             return NULL;
338         }
339
340         if( pi->dl_src.type == AT_ETHER && pi->dl_dst.type == AT_ETHER ) {
341             /* Ethernet */
342             buf = g_strdup_printf("eth.addr eq %s and eth.addr eq %s",
343                 ether_to_str( pi->dl_src.data),
344                 ether_to_str( pi->dl_dst.data));
345         } else {
346             return NULL;
347         }
348         break;
349     default:
350         return NULL;
351     }
352
353     return buf;
354 }
355
356 void
357 conversation_cb(GtkWidget * w, gpointer data _U_, int action)
358 {
359     gchar       *filter;
360     GtkWidget   *filter_te;
361
362     if (cfile.current_frame) {
363         /* create a filter-string based on the selected packet and action */
364         filter = build_conversation_filter(action, TRUE);
365
366         /* Run the display filter so it goes in effect - even if it's the
367         same as the previous display filter. */
368         filter_te = g_object_get_data(G_OBJECT(w), E_DFILTER_TE_KEY);
369         gtk_entry_set_text(GTK_ENTRY(filter_te), filter);
370         main_filter_packets(&cfile, filter, TRUE);
371
372         g_free(filter);
373     }
374 }
375
376 void
377 colorize_conversation_cb(GtkWidget * w _U_, gpointer data _U_, int action)
378 {
379     gchar        *filter = NULL;
380
381     if( (action>>8) == 255 ) {
382         color_filters_reset_tmp();
383         cf_colorize_packets(&cfile);
384     } else if (cfile.current_frame) {
385         if( (action&0xff) == 0 ) {
386             /* colorize_conversation_cb was called from the window-menu
387              * or through an accelerator key. Try to build a conversation
388              * filter in the order TCP, UDP, IP, Ethernet and apply the
389              * coloring */
390             filter = build_conversation_filter(CONV_TCP,FALSE);
391             if( filter == NULL )
392                 filter = build_conversation_filter(CONV_UDP,FALSE);
393             if( filter == NULL )
394                 filter = build_conversation_filter(CONV_IP,FALSE);
395             if( filter == NULL )
396                 filter = build_conversation_filter(CONV_ETHER,FALSE);
397             if( filter == NULL ) {
398                 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Unable to build conversation filter.");
399                 return;
400             }
401         } else {
402             /* create a filter-string based on the selected packet and action */
403             filter = build_conversation_filter(action&0xff, TRUE);
404         }
405
406         if( (action>>8) == 0) {
407             /* Open the "new coloring filter" dialog with the filter */
408             color_display_with_filter(filter);
409         } else {
410             /* Set one of the temporary coloring filters */
411             color_filters_set_tmp((guint8)(action>>8),filter,FALSE);
412             cf_colorize_packets(&cfile);
413         }
414
415         g_free(filter);
416     }
417 }
418
419 /* main menu */
420 static GtkItemFactoryEntry menu_items[] =
421 {
422     {"/_File", NULL, NULL, 0, "<Branch>", NULL,},
423     {"/File/_Open...", "<control>O", GTK_MENU_FUNC(file_open_cmd_cb),
424                              0, "<StockItem>", GTK_STOCK_OPEN,},
425     {"/File/Open _Recent", NULL, NULL, 0, "<Branch>", NULL,},
426     {"/File/_Merge...", NULL, GTK_MENU_FUNC(file_merge_cmd_cb), 0, NULL, NULL,},
427     {"/File/_Close", "<control>W", GTK_MENU_FUNC(file_close_cmd_cb),
428                              0, "<StockItem>", GTK_STOCK_CLOSE,},
429     {"/File/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
430     {"/File/_Save", "<control>S", GTK_MENU_FUNC(file_save_cmd_cb),
431                              0, "<StockItem>", GTK_STOCK_SAVE,},
432     {"/File/Save _As...", "<shift><control>S", GTK_MENU_FUNC(file_save_as_cmd_cb),
433                              0, "<StockItem>", GTK_STOCK_SAVE_AS,},
434     {"/File/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
435     {"/File/File Set", NULL, NULL, 0, "<Branch>", NULL,},
436     {"/File/File Set/List Files", NULL, GTK_MENU_FUNC(fileset_cb), 0, "<StockItem>", WIRESHARK_STOCK_FILE_SET_LIST,},
437     {"/File/File Set/Next File", NULL, GTK_MENU_FUNC(fileset_next_cb), 0, "<StockItem>", WIRESHARK_STOCK_FILE_SET_NEXT,},
438     {"/File/File Set/Previous File", NULL, GTK_MENU_FUNC(fileset_previous_cb), 0, "<StockItem>", WIRESHARK_STOCK_FILE_SET_PREVIOUS,},
439     {"/File/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
440     {"/File/_Export", NULL, NULL, 0, "<Branch>", NULL,},
441 #if _WIN32
442     {"/File/Export/File...", NULL, GTK_MENU_FUNC(export_text_cmd_cb),
443                          0, NULL, NULL,},
444 #else
445     {"/File/Export/as \"Plain _Text\" file...", NULL, GTK_MENU_FUNC(export_text_cmd_cb),
446                              0, NULL, NULL,},
447     {"/File/Export/as \"_PostScript\" file...", NULL, GTK_MENU_FUNC(export_ps_cmd_cb),
448                              0, NULL, NULL,},
449     {"/File/Export/as \"_CSV\" (Comma Separated Values packet summary) file...",
450                              NULL, GTK_MENU_FUNC(export_csv_cmd_cb), 0, NULL, NULL,},
451     {"/File/Export/as \"C _Arrays\" (packet bytes) file...", NULL, GTK_MENU_FUNC(export_carrays_cmd_cb),
452                              0, NULL, NULL,},
453     {"/File/Export/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
454     {"/File/Export/as XML - \"P_SML\" (packet summary) file...", NULL, GTK_MENU_FUNC(export_psml_cmd_cb),
455                              0, NULL, NULL,},
456     {"/File/Export/as XML - \"P_DML\" (packet details) file...", NULL, GTK_MENU_FUNC(export_pdml_cmd_cb),
457                              0, NULL, NULL,},
458     {"/File/Export/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
459 #endif
460     {"/File/Export/Selected Packet _Bytes...", "<control>H", GTK_MENU_FUNC(savehex_cb),
461                              0, NULL, NULL,},
462     {"/File/Export/_Objects/_HTTP", NULL, GTK_MENU_FUNC(eo_http_cb), 0, NULL, NULL,},
463     {"/File/Export/_Objects/_DICOM", NULL, GTK_MENU_FUNC(eo_dicom_cb), 0, NULL, NULL,},
464
465     {"/File/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
466     {"/File/_Print...", "<control>P", GTK_MENU_FUNC(file_print_cmd_cb),
467                              0, "<StockItem>", GTK_STOCK_PRINT,},
468     {"/File/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
469     {"/File/_Quit", "<control>Q", GTK_MENU_FUNC(file_quit_cmd_cb),
470                              0, "<StockItem>", GTK_STOCK_QUIT,},
471     {"/_Edit", NULL, NULL, 0, "<Branch>", NULL,},
472     {"/Edit/Copy", NULL, NULL, 0, "<Branch>", NULL,},
473     {"/Edit/Copy/As Filter", "<shift><control>C", GTK_MENU_FUNC(match_selected_ptree_cb),
474                        MATCH_SELECTED_REPLACE|MATCH_SELECTED_COPY_ONLY, NULL, NULL,},
475 #if 0
476     /* Un-#if this when we actually implement Cut/Copy/Paste. */
477     {"/Edit/Cut", "<control>X", NULL,
478                              0, "<StockItem>", GTK_STOCK_CUT,},
479     {"/Edit/Copy", "<control>C", NULL,
480                              0, "<StockItem>", GTK_STOCK_COPY,},
481     {"/Edit/Paste", "<control>V", NULL,
482                              0, "<StockItem>", GTK_STOCK_PASTE,},
483 #endif
484     {"/Edit/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
485     {"/Edit/_Find Packet...", "<control>F",
486                              GTK_MENU_FUNC(find_frame_cb), 0, "<StockItem>", GTK_STOCK_FIND,},
487     {"/Edit/Find Ne_xt", "<control>N", GTK_MENU_FUNC(find_next_cb), 0, NULL, NULL,},
488     {"/Edit/Find Pre_vious", "<control>B", GTK_MENU_FUNC(find_previous_cb), 0, NULL, NULL,},
489     {"/Edit/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
490     {"/Edit/_Mark Packet (toggle)", "<control>M", GTK_MENU_FUNC(packet_list_mark_frame_cb),
491                        0, NULL, NULL,},
492     {"/Edit/Find Next Mark", "<shift><control>N", GTK_MENU_FUNC(find_next_mark_cb),
493                        0, NULL, NULL,},
494     {"/Edit/Find Previous Mark", "<shift><control>B", GTK_MENU_FUNC(find_prev_mark_cb),
495                        0, NULL, NULL,},
496     {"/Edit/Mark _All Packets", "<control>A", GTK_MENU_FUNC(packet_list_mark_all_frames_cb),
497                        0, NULL, NULL,},
498     {"/Edit/_Unmark All Packets", "<control>D", GTK_MENU_FUNC(packet_list_unmark_all_frames_cb),
499                        0, NULL, NULL,},
500     {"/Edit/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
501     {"/Edit/Set Time Reference (toggle)", "<control>T", GTK_MENU_FUNC(reftime_frame_cb),
502                         REFTIME_TOGGLE, "<StockItem>", WIRESHARK_STOCK_TIME,},
503     {"/Edit/Find Next Reference", "<alt><shift><control>N", GTK_MENU_FUNC(reftime_frame_cb), REFTIME_FIND_NEXT, NULL, NULL,},
504     {"/Edit/Find Previous Reference", "<alt><shift><control>B", GTK_MENU_FUNC(reftime_frame_cb), REFTIME_FIND_PREV, NULL, NULL,},
505     {"/Edit/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
506     {"/Edit/_Configuration Profiles...", "<shift><control>A", GTK_MENU_FUNC(profile_dialog_cb), 0, NULL, NULL,},
507     {"/Edit/_Preferences...", "<shift><control>P", GTK_MENU_FUNC(prefs_cb),
508                              0, "<StockItem>", GTK_STOCK_PREFERENCES,},
509     {"/_View", NULL, NULL, 0, "<Branch>", NULL,},
510     {"/View/_Main Toolbar", NULL, GTK_MENU_FUNC(show_hide_cb), SHOW_HIDE_MAIN_TOOLBAR, "<CheckItem>", NULL,},
511     {"/View/_Filter Toolbar", NULL, GTK_MENU_FUNC(show_hide_cb), SHOW_HIDE_FILTER_TOOLBAR, "<CheckItem>", NULL,},
512 #ifdef HAVE_AIRPCAP
513     {"/View/_Wireless Toolbar", NULL, GTK_MENU_FUNC(show_hide_cb), SHOW_HIDE_AIRPCAP_TOOLBAR, "<CheckItem>", NULL,},
514 #endif
515     {"/View/_Statusbar", NULL, GTK_MENU_FUNC(show_hide_cb), SHOW_HIDE_STATUSBAR, "<CheckItem>", NULL,},
516     {"/View/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
517     {"/View/Packet _List", NULL, GTK_MENU_FUNC(show_hide_cb), SHOW_HIDE_PACKET_LIST, "<CheckItem>", NULL,},
518     {"/View/Packet _Details", NULL, GTK_MENU_FUNC(show_hide_cb), SHOW_HIDE_TREE_VIEW, "<CheckItem>", NULL,},
519     {"/View/Packet _Bytes", NULL, GTK_MENU_FUNC(show_hide_cb), SHOW_HIDE_BYTE_VIEW, "<CheckItem>", NULL,},
520     {"/View/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
521     {"/View/_Time Display Format", NULL, NULL, 0, "<Branch>", NULL,},
522     {"/View/Time Display Format/Date and Time of Day:   1970-01-01 01:02:03.123456", "<control>1", GTK_MENU_FUNC(timestamp_format_cb),
523                         TS_ABSOLUTE_WITH_DATE, "<RadioItem>", NULL,},
524     {"/View/Time Display Format/Time of Day:   01:02:03.123456", "<control>2", GTK_MENU_FUNC(timestamp_format_cb), 
525                         TS_ABSOLUTE, "/View/Time Display Format/Date and Time of Day:   1970-01-01 01:02:03.123456", NULL,},
526     {"/View/Time Display Format/Seconds Since Epoch (1970-01-01):   1234567890.123456", "<control>3", GTK_MENU_FUNC(timestamp_format_cb),
527                         TS_EPOCH, "/View/Time Display Format/Date and Time of Day:   1970-01-01 01:02:03.123456", NULL,},
528     {"/View/Time Display Format/Seconds Since Beginning of Capture:   123.123456", "<control>4", GTK_MENU_FUNC(timestamp_format_cb),
529                         TS_RELATIVE, "/View/Time Display Format/Date and Time of Day:   1970-01-01 01:02:03.123456", NULL,},
530     {"/View/Time Display Format/Seconds Since Previous Captured Packet:   1.123456", "<control>5", GTK_MENU_FUNC(timestamp_format_cb),
531                         TS_DELTA, "/View/Time Display Format/Date and Time of Day:   1970-01-01 01:02:03.123456", NULL,},
532     {"/View/Time Display Format/Seconds Since Previous Displayed Packet:   1.123456", "<control>6", GTK_MENU_FUNC(timestamp_format_cb),
533                         TS_DELTA_DIS, "/View/Time Display Format/Date and Time of Day:   1970-01-01 01:02:03.123456", NULL,},
534     {"/View/Time Display Format/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
535     {"/View/Time Display Format/Automatic (File Format Precision)", NULL, GTK_MENU_FUNC(timestamp_precision_cb),
536                         TS_PREC_AUTO, "<RadioItem>", NULL,},
537     {"/View/Time Display Format/Seconds:   0", NULL, GTK_MENU_FUNC(timestamp_precision_cb),
538                         TS_PREC_FIXED_SEC, "/View/Time Display Format/Automatic (File Format Precision)", NULL,},
539     {"/View/Time Display Format/Deciseconds:   0.1", NULL, GTK_MENU_FUNC(timestamp_precision_cb),
540                         TS_PREC_FIXED_DSEC, "/View/Time Display Format/Automatic (File Format Precision)", NULL,},
541     {"/View/Time Display Format/Centiseconds:   0.12", NULL, GTK_MENU_FUNC(timestamp_precision_cb),
542                         TS_PREC_FIXED_CSEC, "/View/Time Display Format/Automatic (File Format Precision)", NULL,},
543     {"/View/Time Display Format/Milliseconds:   0.123", NULL, GTK_MENU_FUNC(timestamp_precision_cb),
544                         TS_PREC_FIXED_MSEC, "/View/Time Display Format/Automatic (File Format Precision)", NULL,},
545     {"/View/Time Display Format/Microseconds:   0.123456", NULL, GTK_MENU_FUNC(timestamp_precision_cb),
546                         TS_PREC_FIXED_USEC, "/View/Time Display Format/Automatic (File Format Precision)", NULL,},
547     {"/View/Time Display Format/Nanoseconds:   0.123456789", NULL, GTK_MENU_FUNC(timestamp_precision_cb),
548                         TS_PREC_FIXED_NSEC, "/View/Time Display Format/Automatic (File Format Precision)", NULL,},
549     {"/View/Name Resol_ution", NULL, NULL, 0, "<Branch>", NULL,},
550     {"/View/Name Resolution/_Resolve Name", NULL, GTK_MENU_FUNC(resolve_name_cb), 0, NULL, NULL,},
551     {"/View/Name Resolution/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
552     {"/View/Name Resolution/Enable for _MAC Layer", NULL, GTK_MENU_FUNC(name_resolution_cb), RESOLV_MAC, "<CheckItem>", NULL,},
553     {"/View/Name Resolution/Enable for _Network Layer", NULL, GTK_MENU_FUNC(name_resolution_cb), RESOLV_NETWORK, "<CheckItem>", NULL,},
554     {"/View/Name Resolution/Enable for _Transport Layer", NULL, GTK_MENU_FUNC(name_resolution_cb), RESOLV_TRANSPORT, "<CheckItem>", NULL,},
555     {"/View/Colorize Packet List", NULL, colorize_cb, 0, "<CheckItem>", NULL,},
556 #ifdef HAVE_LIBPCAP
557     {"/View/Auto Scroll in Li_ve Capture", NULL, GTK_MENU_FUNC(auto_scroll_live_cb), 0, "<CheckItem>", NULL,},
558 #endif
559     {"/View/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
560     {"/View/_Zoom In", "<control>plus", GTK_MENU_FUNC(view_zoom_in_cb),
561                              0, "<StockItem>", GTK_STOCK_ZOOM_IN,},
562     {"/View/Zoom _Out", "<control>minus", GTK_MENU_FUNC(view_zoom_out_cb),
563                              0, "<StockItem>", GTK_STOCK_ZOOM_OUT,},
564     {"/View/_Normal Size", "<control>equal", GTK_MENU_FUNC(view_zoom_100_cb),
565                              0, "<StockItem>", GTK_STOCK_ZOOM_100,},
566     {"/View/Resize All Columns", "<shift><control>R", GTK_MENU_FUNC(packet_list_resize_columns_cb),
567                        0, "<StockItem>", WIRESHARK_STOCK_RESIZE_COLUMNS,},
568     {"/View/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
569     {"/View/E_xpand Subtrees", "<shift>Right", GTK_MENU_FUNC(expand_tree_cb), 0, NULL, NULL,},
570     {"/View/_Expand All", "<control>Right", GTK_MENU_FUNC(expand_all_cb),
571                        0, NULL, NULL,},
572     {"/View/Collapse _All", "<control>Left", GTK_MENU_FUNC(collapse_all_cb),
573                        0, NULL, NULL,},
574     {"/View/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
575     {"/View/Colorize Conversation", NULL, NULL, 0, "<Branch>",NULL,},
576     {"/View/Colorize Conversation/Color 1", "<control>1",
577                        GTK_MENU_FUNC(colorize_conversation_cb), 1*256, "<StockItem>", WIRESHARK_STOCK_COLOR1,},
578     {"/View/Colorize Conversation/Color 2", "<control>2",
579                        GTK_MENU_FUNC(colorize_conversation_cb), 2*256, "<StockItem>", WIRESHARK_STOCK_COLOR2,},
580     {"/View/Colorize Conversation/Color 3", "<control>3",
581                        GTK_MENU_FUNC(colorize_conversation_cb), 3*256, "<StockItem>", WIRESHARK_STOCK_COLOR3,},
582     {"/View/Colorize Conversation/Color 4", "<control>4",
583                        GTK_MENU_FUNC(colorize_conversation_cb), 4*256, "<StockItem>", WIRESHARK_STOCK_COLOR4,},
584     {"/View/Colorize Conversation/Color 5", "<control>5",
585                        GTK_MENU_FUNC(colorize_conversation_cb), 5*256, "<StockItem>", WIRESHARK_STOCK_COLOR5,},
586     {"/View/Colorize Conversation/Color 6", "<control>6",
587                        GTK_MENU_FUNC(colorize_conversation_cb), 6*256, "<StockItem>", WIRESHARK_STOCK_COLOR6,},
588     {"/View/Colorize Conversation/Color 7", "<control>7",
589                        GTK_MENU_FUNC(colorize_conversation_cb), 7*256, "<StockItem>", WIRESHARK_STOCK_COLOR7,},
590     {"/View/Colorize Conversation/Color 8", "<control>8",
591                        GTK_MENU_FUNC(colorize_conversation_cb), 8*256, "<StockItem>", WIRESHARK_STOCK_COLOR8,},
592     {"/View/Colorize Conversation/Color 9", "<control>9",
593                        GTK_MENU_FUNC(colorize_conversation_cb), 9*256, "<StockItem>", WIRESHARK_STOCK_COLOR9,},
594     {"/View/Colorize Conversation/Color 10", "<control>0",
595                        GTK_MENU_FUNC(colorize_conversation_cb), 10*256, "<StockItem>", WIRESHARK_STOCK_COLOR0,},
596     {"/View/Colorize Conversation/<separator>", NULL,
597                        NULL, 0, "<Separator>",NULL,},
598     {"/View/Colorize Conversation/New Coloring Rule...", NULL,
599                        GTK_MENU_FUNC(colorize_conversation_cb), 0, "<StockItem>", GTK_STOCK_SELECT_COLOR,},
600     {"/View/Reset Coloring 1-10", "<control>space",
601                        GTK_MENU_FUNC(colorize_conversation_cb), 255*256, NULL, NULL,},
602     {"/View/_Coloring Rules...", NULL, color_display_cb,
603                        0, "<StockItem>", GTK_STOCK_SELECT_COLOR,},
604     {"/View/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
605
606
607     {"/View/Show Packet in New _Window", NULL,
608                        GTK_MENU_FUNC(new_window_cb), 0, NULL, NULL,},
609     {"/View/_Reload", "<control>R", GTK_MENU_FUNC(file_reload_cmd_cb),
610                              0, "<StockItem>", GTK_STOCK_REFRESH,},
611     {"/_Go", NULL, NULL, 0, "<Branch>", NULL,},
612     {"/Go/_Back", "<alt>Left",
613                              GTK_MENU_FUNC(history_back_cb), 0, "<StockItem>", GTK_STOCK_GO_BACK,},
614     {"/Go/_Forward", "<alt>Right",
615                              GTK_MENU_FUNC(history_forward_cb), 0, "<StockItem>", GTK_STOCK_GO_FORWARD,},
616     {"/Go/_Go to Packet...", "<control>G",
617                              GTK_MENU_FUNC(goto_frame_cb), 0, "<StockItem>", GTK_STOCK_JUMP_TO,},
618     {"/Go/Go to _Corresponding Packet", NULL, GTK_MENU_FUNC(goto_framenum_cb),
619                        0, NULL, NULL,},
620     {"/Go/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
621     {"/Go/Previous Packet", "<control>Up",
622                              GTK_MENU_FUNC(packet_list_prev), 0, "<StockItem>", GTK_STOCK_GO_UP,},
623     {"/Go/Next Packet", "<control>Down",
624                              GTK_MENU_FUNC(packet_list_next), 0, "<StockItem>", GTK_STOCK_GO_DOWN,},
625     {"/Go/F_irst Packet", "Home",
626                              GTK_MENU_FUNC(goto_top_frame_cb), 0, "<StockItem>", GTK_STOCK_GOTO_TOP,},
627     {"/Go/_Last Packet", "End",
628                              GTK_MENU_FUNC(goto_bottom_frame_cb), 0, "<StockItem>", GTK_STOCK_GOTO_BOTTOM,},
629 #ifdef HAVE_LIBPCAP
630     {"/_Capture", NULL, NULL, 0, "<Branch>", NULL,},
631     {"/Capture/_Interfaces...", "<control>I",
632                              GTK_MENU_FUNC(capture_if_cb), 0, "<StockItem>", WIRESHARK_STOCK_CAPTURE_INTERFACES,},
633     {"/Capture/_Options...", "<control>K",
634                              GTK_MENU_FUNC(capture_prep_cb), 0, "<StockItem>", WIRESHARK_STOCK_CAPTURE_OPTIONS,},
635     {"/Capture/_Start", "<control>E",
636                              GTK_MENU_FUNC(capture_start_cb), 0, "<StockItem>", WIRESHARK_STOCK_CAPTURE_START,},
637     {"/Capture/S_top", "<control>E", GTK_MENU_FUNC(capture_stop_cb),
638                              0, "<StockItem>", WIRESHARK_STOCK_CAPTURE_STOP,},
639     {"/Capture/_Restart", "<control>R", GTK_MENU_FUNC(capture_restart_cb),
640                              0, "<StockItem>", WIRESHARK_STOCK_CAPTURE_RESTART,},
641     {"/Capture/Capture _Filters...", NULL, GTK_MENU_FUNC(cfilter_dialog_cb),
642                        0, "<StockItem>", WIRESHARK_STOCK_CAPTURE_FILTER,},
643 #endif /* HAVE_LIBPCAP */
644     {"/_Analyze", NULL, NULL, 0, "<Branch>", NULL,},
645     {"/Analyze/_Display Filters...", NULL, GTK_MENU_FUNC(dfilter_dialog_cb),
646                        0, "<StockItem>", WIRESHARK_STOCK_DISPLAY_FILTER,},
647     {"/Analyze/Display Filter _Macros...", NULL, GTK_MENU_FUNC(macros_dialog_cb), 0, NULL, NULL,},
648     {"/Analyze/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
649     {"/Analyze/Appl_y as Filter", NULL, NULL, 0, "<Branch>", NULL,},
650     {"/Analyze/Apply as Filter/_Selected", NULL, GTK_MENU_FUNC(match_selected_ptree_cb),
651                        MATCH_SELECTED_REPLACE|MATCH_SELECTED_APPLY_NOW, NULL, NULL,},
652     {"/Analyze/Apply as Filter/_Not Selected", NULL, GTK_MENU_FUNC(match_selected_ptree_cb),
653                        MATCH_SELECTED_NOT|MATCH_SELECTED_APPLY_NOW, NULL, NULL,},
654     {"/Analyze/Apply as Filter/... _and Selected", NULL, GTK_MENU_FUNC(match_selected_ptree_cb),
655                        MATCH_SELECTED_AND|MATCH_SELECTED_APPLY_NOW, NULL, NULL,},
656     {"/Analyze/Apply as Filter/... _or Selected", NULL, GTK_MENU_FUNC(match_selected_ptree_cb),
657                        MATCH_SELECTED_OR|MATCH_SELECTED_APPLY_NOW, NULL, NULL,},
658     {"/Analyze/Apply as Filter/... a_nd not Selected", NULL, GTK_MENU_FUNC(match_selected_ptree_cb),
659                        MATCH_SELECTED_AND_NOT|MATCH_SELECTED_APPLY_NOW, NULL, NULL,},
660     {"/Analyze/Apply as Filter/... o_r not Selected", NULL, GTK_MENU_FUNC(match_selected_ptree_cb),
661                        MATCH_SELECTED_OR_NOT|MATCH_SELECTED_APPLY_NOW, NULL, NULL,},
662     {"/Analyze/_Prepare a Filter", NULL, NULL, 0, "<Branch>", NULL,},
663     {"/Analyze/Prepare a Filter/_Selected", NULL, GTK_MENU_FUNC(match_selected_ptree_cb),
664                        MATCH_SELECTED_REPLACE, NULL, NULL,},
665     {"/Analyze/Prepare a Filter/_Not Selected", NULL, GTK_MENU_FUNC(match_selected_ptree_cb),
666                        MATCH_SELECTED_NOT, NULL, NULL,},
667     {"/Analyze/Prepare a Filter/... _and Selected", NULL, GTK_MENU_FUNC(match_selected_ptree_cb),
668                        MATCH_SELECTED_AND, NULL, NULL,},
669     {"/Analyze/Prepare a Filter/... _or Selected", NULL, GTK_MENU_FUNC(match_selected_ptree_cb),
670                        MATCH_SELECTED_OR, NULL, NULL,},
671     {"/Analyze/Prepare a Filter/... a_nd not Selected", NULL, GTK_MENU_FUNC(match_selected_ptree_cb),
672                        MATCH_SELECTED_AND_NOT, NULL, NULL,},
673     {"/Analyze/Prepare a Filter/... o_r not Selected", NULL, GTK_MENU_FUNC(match_selected_ptree_cb),
674                        MATCH_SELECTED_OR_NOT, NULL, NULL,},
675     {"/Analyze/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
676     {"/Analyze/_Enabled Protocols...", "<shift><control>E", GTK_MENU_FUNC(proto_cb), 
677                        0, "<StockItem>", WIRESHARK_STOCK_CHECKBOX,},
678     {"/Analyze/Decode _As...", NULL, GTK_MENU_FUNC(decode_as_cb),
679                        0, "<StockItem>", WIRESHARK_STOCK_DECODE_AS,},
680     {"/Analyze/_User Specified Decodes...", NULL,
681                        GTK_MENU_FUNC(decode_show_cb), 0, "<StockItem>", WIRESHARK_STOCK_DECODE_AS,},
682     {"/Analyze/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
683     {"/Analyze/_Follow TCP Stream", NULL,
684                        GTK_MENU_FUNC(follow_tcp_stream_cb), 0, NULL, NULL,},
685     {"/Analyze/_Follow UDP Stream", NULL,
686                        GTK_MENU_FUNC(follow_udp_stream_cb), 0, NULL, NULL,},
687     {"/Analyze/_Follow SSL Stream", NULL,
688                        GTK_MENU_FUNC(follow_ssl_stream_cb), 0, NULL, NULL,},
689     {"/_Statistics", NULL, NULL, 0, "<Branch>", NULL,},
690     {"/Statistics/_Summary", NULL, GTK_MENU_FUNC(summary_open_cb), 0, "<StockItem>", GTK_STOCK_PROPERTIES,},
691     {"/Statistics/_Protocol Hierarchy", NULL,
692                        GTK_MENU_FUNC(proto_hier_stats_cb), 0, NULL, NULL,},
693     {"/Statistics/Conversations", NULL,
694                        GTK_MENU_FUNC(init_conversation_notebook_cb), 0, "<StockItem>", WIRESHARK_STOCK_CONVERSATIONS,},
695     {"/Statistics/Endpoints", NULL,
696                        GTK_MENU_FUNC(init_hostlist_notebook_cb), 0, "<StockItem>", WIRESHARK_STOCK_ENDPOINTS,},
697     {"/Telephon_y", NULL, NULL, 0, "<Branch>", NULL,},
698     {"/_Tools", NULL, NULL, 0, "<Branch>", NULL,},
699     {"/Tools/Firewall ACL Rules", NULL,
700                        firewall_rule_cb, 0, NULL, NULL,},
701     {"/_Help", NULL, NULL, 0, "<Branch>", NULL,},
702     {"/Help/_Contents", "F1", GTK_MENU_FUNC(topic_menu_cb), HELP_CONTENT, "<StockItem>", GTK_STOCK_HELP,},
703     {"/Help/FAQ's", NULL, GTK_MENU_FUNC(topic_menu_cb), ONLINEPAGE_FAQ, NULL, NULL,},
704     {"/Help/Manual Pages", NULL, NULL, 0, "<Branch>", NULL,},
705     {"/Help/Manual Pages/Wireshark", NULL, GTK_MENU_FUNC(topic_menu_cb), LOCALPAGE_MAN_WIRESHARK, NULL, NULL,},
706     {"/Help/Manual Pages/Wireshark Filter", NULL, GTK_MENU_FUNC(topic_menu_cb), LOCALPAGE_MAN_WIRESHARK_FILTER, NULL, NULL,},
707     {"/Help/Manual Pages/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
708     {"/Help/Manual Pages/TShark", NULL, GTK_MENU_FUNC(topic_menu_cb), LOCALPAGE_MAN_TSHARK, NULL, NULL,},
709     {"/Help/Manual Pages/RawShark", NULL, GTK_MENU_FUNC(topic_menu_cb), LOCALPAGE_MAN_RAWSHARK, NULL, NULL,},
710     {"/Help/Manual Pages/Dumpcap", NULL, GTK_MENU_FUNC(topic_menu_cb), LOCALPAGE_MAN_DUMPCAP, NULL, NULL,},
711     {"/Help/Manual Pages/Mergecap", NULL, GTK_MENU_FUNC(topic_menu_cb), LOCALPAGE_MAN_MERGECAP, NULL, NULL,},
712     {"/Help/Manual Pages/Editcap", NULL, GTK_MENU_FUNC(topic_menu_cb), LOCALPAGE_MAN_EDITCAP, NULL, NULL,},
713     {"/Help/Manual Pages/Text2pcap", NULL, GTK_MENU_FUNC(topic_menu_cb), LOCALPAGE_MAN_TEXT2PCAP, NULL, NULL,},
714     {"/Help/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
715     {"/Help/Website", NULL, GTK_MENU_FUNC(topic_menu_cb), ONLINEPAGE_HOME, "<StockItem>", GTK_STOCK_HOME,},
716     {"/Help/Wiki", NULL, GTK_MENU_FUNC(topic_menu_cb), ONLINEPAGE_WIKI, "<StockItem>", WIRESHARK_STOCK_WIKI,},
717     {"/Help/Downloads", NULL, GTK_MENU_FUNC(topic_menu_cb), ONLINEPAGE_DOWNLOAD, NULL, NULL,},
718     {"/Help/Sample Captures", NULL, GTK_MENU_FUNC(topic_menu_cb), ONLINEPAGE_SAMPLE_FILES, NULL, NULL,},
719     {"/Help/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
720     {"/Help/_Supported Protocols (slow!)", NULL, GTK_MENU_FUNC(supported_cb), 0, NULL, NULL,},
721     {"/Help/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
722     {"/Help/_About Wireshark", NULL, GTK_MENU_FUNC(about_wireshark_cb),
723                        0, "<StockItem>", WIRESHARK_STOCK_ABOUT}
724 };
725
726
727 /* calculate the number of menu_items */
728 static int nmenu_items = sizeof(menu_items) / sizeof(menu_items[0]);
729
730 /* packet list popup */
731 static GtkItemFactoryEntry packet_list_menu_items[] =
732 {
733     {"/Mark Packet (toggle)", NULL, GTK_MENU_FUNC(packet_list_mark_frame_cb), 0, NULL, NULL,},
734     {"/Set Time Reference (toggle)", NULL, GTK_MENU_FUNC(reftime_frame_cb), REFTIME_TOGGLE, "<StockItem>", WIRESHARK_STOCK_TIME,},
735
736     {"/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
737
738     {"/Apply as Filter", NULL, NULL, 0, "<Branch>", NULL,},
739     {"/Apply as Filter/_Selected", NULL, GTK_MENU_FUNC(match_selected_plist_cb),
740                        MATCH_SELECTED_REPLACE|MATCH_SELECTED_APPLY_NOW, NULL, NULL,},
741     {"/Apply as Filter/_Not Selected", NULL, GTK_MENU_FUNC(match_selected_plist_cb),
742                        MATCH_SELECTED_NOT|MATCH_SELECTED_APPLY_NOW, NULL, NULL,},
743     {"/Apply as Filter/... _and Selected", NULL, GTK_MENU_FUNC(match_selected_plist_cb),
744                        MATCH_SELECTED_AND|MATCH_SELECTED_APPLY_NOW, NULL, NULL,},
745     {"/Apply as Filter/... _or Selected", NULL, GTK_MENU_FUNC(match_selected_plist_cb),
746                        MATCH_SELECTED_OR|MATCH_SELECTED_APPLY_NOW, NULL, NULL,},
747     {"/Apply as Filter/... a_nd not Selected", NULL, GTK_MENU_FUNC(match_selected_plist_cb),
748                        MATCH_SELECTED_AND_NOT|MATCH_SELECTED_APPLY_NOW, NULL, NULL,},
749     {"/Apply as Filter/... o_r not Selected", NULL, GTK_MENU_FUNC(match_selected_plist_cb),
750                        MATCH_SELECTED_OR_NOT|MATCH_SELECTED_APPLY_NOW, NULL, NULL,},
751
752     {"/Prepare a Filter", NULL, NULL, 0, "<Branch>", NULL,},
753     {"/Prepare a Filter/_Selected", NULL, GTK_MENU_FUNC(match_selected_plist_cb),
754                        MATCH_SELECTED_REPLACE, NULL, NULL,},
755     {"/Prepare a Filter/_Not Selected", NULL, GTK_MENU_FUNC(match_selected_plist_cb),
756                        MATCH_SELECTED_NOT, NULL, NULL,},
757     {"/Prepare a Filter/... _and Selected", NULL, GTK_MENU_FUNC(match_selected_plist_cb),
758                        MATCH_SELECTED_AND, NULL, NULL,},
759     {"/Prepare a Filter/... _or Selected", NULL, GTK_MENU_FUNC(match_selected_plist_cb),
760                        MATCH_SELECTED_OR, NULL, NULL,},
761     {"/Prepare a Filter/... a_nd not Selected", NULL, GTK_MENU_FUNC(match_selected_plist_cb),
762                        MATCH_SELECTED_AND_NOT, NULL, NULL,},
763     {"/Prepare a Filter/... o_r not Selected", NULL, GTK_MENU_FUNC(match_selected_plist_cb),
764                        MATCH_SELECTED_OR_NOT, NULL, NULL,},
765
766     {"/Conversation Filter", NULL, NULL, 0, "<Branch>",NULL,},
767     {"/Conversation Filter/Ethernet", NULL, GTK_MENU_FUNC(conversation_cb),
768                        CONV_ETHER, NULL, NULL,},
769     {"/Conversation Filter/IP", NULL, GTK_MENU_FUNC(conversation_cb),
770                        CONV_IP, NULL, NULL,},
771     {"/Conversation Filter/TCP", NULL, GTK_MENU_FUNC(conversation_cb),
772                        CONV_TCP, NULL, NULL,},
773     {"/Conversation Filter/UDP", NULL, GTK_MENU_FUNC(conversation_cb),
774                        CONV_UDP, NULL, NULL,},
775     {"/Conversation Filter/PN-CBA Server", NULL, GTK_MENU_FUNC(conversation_cb),
776                        CONV_CBA, NULL, NULL,},
777
778     {"/Colorize Conversation", NULL, NULL, 0, "<Branch>",NULL,},
779     {"/Colorize Conversation/Ethernet", NULL, NULL, 0, "<Branch>",NULL,},
780     {"/Colorize Conversation/Ethernet/Color 1", NULL,
781                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_ETHER+1*256, "<StockItem>", WIRESHARK_STOCK_COLOR1,},
782     {"/Colorize Conversation/Ethernet/Color 2", NULL,
783                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_ETHER+2*256, "<StockItem>", WIRESHARK_STOCK_COLOR2,},
784     {"/Colorize Conversation/Ethernet/Color 3", NULL,
785                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_ETHER+3*256, "<StockItem>", WIRESHARK_STOCK_COLOR3,},
786     {"/Colorize Conversation/Ethernet/Color 4", NULL,
787                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_ETHER+4*256, "<StockItem>", WIRESHARK_STOCK_COLOR4,},
788     {"/Colorize Conversation/Ethernet/Color 5", NULL,
789                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_ETHER+5*256, "<StockItem>", WIRESHARK_STOCK_COLOR5,},
790     {"/Colorize Conversation/Ethernet/Color 6", NULL,
791                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_ETHER+6*256, "<StockItem>", WIRESHARK_STOCK_COLOR6,},
792     {"/Colorize Conversation/Ethernet/Color 7", NULL,
793                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_ETHER+7*256, "<StockItem>", WIRESHARK_STOCK_COLOR7,},
794     {"/Colorize Conversation/Ethernet/Color 8", NULL,
795                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_ETHER+8*256, "<StockItem>", WIRESHARK_STOCK_COLOR8,},
796     {"/Colorize Conversation/Ethernet/Color 9", NULL,
797                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_ETHER+9*256, "<StockItem>", WIRESHARK_STOCK_COLOR9,},
798     {"/Colorize Conversation/Ethernet/Color 10", NULL,
799                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_ETHER+10*256, "<StockItem>", WIRESHARK_STOCK_COLOR0,},
800     {"/Colorize Conversation/Ethernet/<separator>", NULL,
801                        NULL, 0, "<Separator>",NULL,},
802     {"/Colorize Conversation/Ethernet/New Coloring Rule...", NULL,
803                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_ETHER, "<StockItem>", GTK_STOCK_SELECT_COLOR,},
804     {"/Colorize Conversation/IP", NULL, NULL, 0, "<Branch>",NULL,},
805     {"/Colorize Conversation/IP/Color 1", NULL,
806                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_IP+1*256, "<StockItem>", WIRESHARK_STOCK_COLOR1,},
807     {"/Colorize Conversation/IP/Color 2", NULL,
808                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_IP+2*256, "<StockItem>", WIRESHARK_STOCK_COLOR2,},
809     {"/Colorize Conversation/IP/Color 3", NULL,
810                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_IP+3*256, "<StockItem>", WIRESHARK_STOCK_COLOR3,},
811     {"/Colorize Conversation/IP/Color 4", NULL,
812                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_IP+4*256, "<StockItem>", WIRESHARK_STOCK_COLOR4,},
813     {"/Colorize Conversation/IP/Color 5", NULL,
814                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_IP+5*256, "<StockItem>", WIRESHARK_STOCK_COLOR5,},
815     {"/Colorize Conversation/IP/Color 6", NULL,
816                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_IP+6*256, "<StockItem>", WIRESHARK_STOCK_COLOR6,},
817     {"/Colorize Conversation/IP/Color 7", NULL,
818                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_IP+7*256, "<StockItem>", WIRESHARK_STOCK_COLOR7,},
819     {"/Colorize Conversation/IP/Color 8", NULL,
820                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_IP+8*256, "<StockItem>", WIRESHARK_STOCK_COLOR8,},
821     {"/Colorize Conversation/IP/Color 9", NULL,
822                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_IP+9*256, "<StockItem>", WIRESHARK_STOCK_COLOR9,},
823     {"/Colorize Conversation/IP/Color 10", NULL,
824                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_IP+10*256, "<StockItem>", WIRESHARK_STOCK_COLOR0,},
825     {"/Colorize Conversation/IP/<separator>", NULL,
826                        NULL, 0, "<Separator>",NULL,},
827     {"/Colorize Conversation/IP/New Coloring Rule...", NULL,
828                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_IP, "<StockItem>", GTK_STOCK_SELECT_COLOR,},
829     {"/Colorize Conversation/TCP", NULL, NULL, 0, "<Branch>",NULL,},
830     {"/Colorize Conversation/TCP/Color 1", NULL,
831                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_TCP+1*256, "<StockItem>", WIRESHARK_STOCK_COLOR1,},
832     {"/Colorize Conversation/TCP/Color 2", NULL,
833                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_TCP+2*256, "<StockItem>", WIRESHARK_STOCK_COLOR2,},
834     {"/Colorize Conversation/TCP/Color 3", NULL,
835                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_TCP+3*256, "<StockItem>", WIRESHARK_STOCK_COLOR3,},
836     {"/Colorize Conversation/TCP/Color 4", NULL,
837                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_TCP+4*256, "<StockItem>", WIRESHARK_STOCK_COLOR4,},
838     {"/Colorize Conversation/TCP/Color 5", NULL,
839                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_TCP+5*256, "<StockItem>", WIRESHARK_STOCK_COLOR5,},
840     {"/Colorize Conversation/TCP/Color 6", NULL,
841                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_TCP+6*256, "<StockItem>", WIRESHARK_STOCK_COLOR6,},
842     {"/Colorize Conversation/TCP/Color 7", NULL,
843                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_TCP+7*256, "<StockItem>", WIRESHARK_STOCK_COLOR7,},
844     {"/Colorize Conversation/TCP/Color 8", NULL,
845                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_TCP+8*256, "<StockItem>", WIRESHARK_STOCK_COLOR8,},
846     {"/Colorize Conversation/TCP/Color 9", NULL,
847                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_TCP+9*256, "<StockItem>", WIRESHARK_STOCK_COLOR9,},
848     {"/Colorize Conversation/TCP/Color 10", NULL,
849                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_TCP+10*256, "<StockItem>", WIRESHARK_STOCK_COLOR0,},
850     {"/Colorize Conversation/TCP/<separator>", NULL,
851                        NULL, 0, "<Separator>",NULL,},
852     {"/Colorize Conversation/TCP/New Coloring Rule...", NULL,
853                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_TCP, "<StockItem>", GTK_STOCK_SELECT_COLOR,},
854     {"/Colorize Conversation/UDP", NULL, NULL, 0, "<Branch>",NULL,},
855     {"/Colorize Conversation/UDP/Color 1", NULL,
856                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_UDP+1*256, "<StockItem>", WIRESHARK_STOCK_COLOR1,},
857     {"/Colorize Conversation/UDP/Color 2", NULL,
858                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_UDP+2*256, "<StockItem>", WIRESHARK_STOCK_COLOR2,},
859     {"/Colorize Conversation/UDP/Color 3", NULL,
860                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_UDP+3*256, "<StockItem>", WIRESHARK_STOCK_COLOR3,},
861     {"/Colorize Conversation/UDP/Color 4", NULL,
862                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_UDP+4*256, "<StockItem>", WIRESHARK_STOCK_COLOR4,},
863     {"/Colorize Conversation/UDP/Color 5", NULL,
864                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_UDP+5*256, "<StockItem>", WIRESHARK_STOCK_COLOR5,},
865     {"/Colorize Conversation/UDP/Color 6", NULL,
866                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_UDP+6*256, "<StockItem>", WIRESHARK_STOCK_COLOR6,},
867     {"/Colorize Conversation/UDP/Color 7", NULL,
868                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_UDP+7*256, "<StockItem>", WIRESHARK_STOCK_COLOR7,},
869     {"/Colorize Conversation/UDP/Color 8", NULL,
870                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_UDP+8*256, "<StockItem>", WIRESHARK_STOCK_COLOR8,},
871     {"/Colorize Conversation/UDP/Color 9", NULL,
872                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_UDP+9*256, "<StockItem>", WIRESHARK_STOCK_COLOR9,},
873     {"/Colorize Conversation/UDP/Color 10", NULL,
874                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_UDP+10*256, "<StockItem>", WIRESHARK_STOCK_COLOR0,},
875     {"/Colorize Conversation/UDP/<separator>", NULL,
876                        NULL, 0, "<Separator>",NULL,},
877     {"/Colorize Conversation/UDP/New Coloring Rule...", NULL,
878                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_UDP, "<StockItem>", GTK_STOCK_SELECT_COLOR,},
879     {"/Colorize Conversation/PN-CBA Server", NULL, NULL, 0, "<Branch>",NULL,},
880     {"/Colorize Conversation/PN-CBA Server/Color 1", NULL,
881                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_CBA+1*256, "<StockItem>", WIRESHARK_STOCK_COLOR1,},
882     {"/Colorize Conversation/PN-CBA Server/Color 2", NULL,
883                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_CBA+2*256, "<StockItem>", WIRESHARK_STOCK_COLOR2,},
884     {"/Colorize Conversation/PN-CBA Server/Color 3", NULL,
885                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_CBA+3*256, "<StockItem>", WIRESHARK_STOCK_COLOR3,},
886     {"/Colorize Conversation/PN-CBA Server/Color 4", NULL,
887                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_CBA+4*256, "<StockItem>", WIRESHARK_STOCK_COLOR4,},
888     {"/Colorize Conversation/PN-CBA Server/Color 5", NULL,
889                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_CBA+5*256, "<StockItem>", WIRESHARK_STOCK_COLOR5,},
890     {"/Colorize Conversation/PN-CBA Server/Color 6", NULL,
891                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_CBA+6*256, "<StockItem>", WIRESHARK_STOCK_COLOR6,},
892     {"/Colorize Conversation/PN-CBA Server/Color 7", NULL,
893                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_CBA+7*256, "<StockItem>", WIRESHARK_STOCK_COLOR7,},
894     {"/Colorize Conversation/PN-CBA Server/Color 8", NULL,
895                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_CBA+8*256, "<StockItem>", WIRESHARK_STOCK_COLOR8,},
896     {"/Colorize Conversation/PN-CBA Server/Color 9", NULL,
897                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_CBA+9*256, "<StockItem>", WIRESHARK_STOCK_COLOR9,},
898     {"/Colorize Conversation/PN-CBA Server/Color 10", NULL,
899                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_CBA+10*256, "<StockItem>", WIRESHARK_STOCK_COLOR0,},
900     {"/Colorize Conversation/PN-CBA Server/<separator>", NULL,
901                        NULL, 0, "<Separator>",NULL,},
902     {"/Colorize Conversation/PN-CBA Server/New Coloring Rule...", NULL,
903                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_CBA, "<StockItem>", GTK_STOCK_SELECT_COLOR,},
904
905     {"/SCTP", NULL, NULL, 0, "<Branch>",NULL,},
906     {"/SCTP/Analyse this Association", NULL, GTK_MENU_FUNC(sctp_analyse_start),
907                        0, NULL,NULL,},
908     {"/SCTP/Prepare Filter for this Association", NULL, (sctp_set_assoc_filter),
909                        0, NULL,NULL,},
910
911     {"/Follow TCP Stream", NULL, (follow_tcp_stream_cb),
912                        0, NULL, NULL,},
913     {"/Follow UDP Stream", NULL, (follow_udp_stream_cb),
914                        0, NULL, NULL,},
915     {"/Follow SSL Stream", NULL, (follow_ssl_stream_cb),
916                        0, NULL, NULL,},
917
918     {"/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
919
920     {"/Copy", NULL, NULL, 0, "<Branch>", NULL,},
921     {"/Copy/Summary (Text)", NULL, GTK_MENU_FUNC(packet_list_copy_summary_cb), CS_TEXT, NULL, NULL,},
922     {"/Copy/Summary (CSV)", NULL, GTK_MENU_FUNC(packet_list_copy_summary_cb), CS_CSV, NULL, NULL,},
923     {"/Copy/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
924     {"/Copy/As Filter", NULL, GTK_MENU_FUNC(match_selected_plist_cb),
925                        MATCH_SELECTED_REPLACE|MATCH_SELECTED_COPY_ONLY, NULL, NULL,},
926     {"/Copy/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
927     {"/Copy/Bytes (Offset Hex Text)", NULL, GTK_MENU_FUNC(copy_hex_cb), CD_ALLINFO, NULL, NULL,},
928     {"/Copy/Bytes (Offset Hex)", NULL, GTK_MENU_FUNC(copy_hex_cb), CD_HEXCOLUMNS, NULL, NULL,},
929     {"/Copy/Bytes (Printable Text Only)", NULL, GTK_MENU_FUNC(copy_hex_cb), CD_TEXTONLY, NULL, NULL,},
930     {"/Copy/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
931     {"/Copy/Bytes (Hex Stream)", NULL, GTK_MENU_FUNC(copy_hex_cb), CD_HEX, NULL, NULL,},
932     {"/Copy/Bytes (Binary Stream)", NULL, GTK_MENU_FUNC(copy_hex_cb), CD_BINARY, NULL, NULL,},
933
934     {"/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
935
936     {"/Decode As...", NULL, GTK_MENU_FUNC(decode_as_cb), 0, "<StockItem>", WIRESHARK_STOCK_DECODE_AS,},
937     {"/Print...", NULL, GTK_MENU_FUNC(file_print_selected_cmd_cb), 0, "<StockItem>", GTK_STOCK_PRINT,},
938     {"/Show Packet in New Window", NULL, GTK_MENU_FUNC(new_window_cb),
939                        0, NULL, NULL}
940 };
941
942 static GtkItemFactoryEntry tree_view_menu_items[] =
943 {
944
945     {"/Expand Subtrees", NULL, GTK_MENU_FUNC(expand_tree_cb), 0, NULL, NULL,},
946     {"/Expand All", NULL, GTK_MENU_FUNC(expand_all_cb), 0, NULL, NULL,},
947     {"/Collapse All", NULL, GTK_MENU_FUNC(collapse_all_cb), 0, NULL, NULL,},
948
949     {"/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
950
951     {"/Apply as Filter", NULL, NULL, 0, "<Branch>", NULL,},
952     {"/Apply as Filter/_Selected", NULL, GTK_MENU_FUNC(match_selected_ptree_cb),
953                        MATCH_SELECTED_REPLACE|MATCH_SELECTED_APPLY_NOW, NULL, NULL,},
954     {"/Apply as Filter/_Not Selected", NULL, GTK_MENU_FUNC(match_selected_ptree_cb),
955                        MATCH_SELECTED_NOT|MATCH_SELECTED_APPLY_NOW, NULL, NULL,},
956     {"/Apply as Filter/... _and Selected", NULL, GTK_MENU_FUNC(match_selected_ptree_cb),
957                        MATCH_SELECTED_AND|MATCH_SELECTED_APPLY_NOW, NULL, NULL,},
958     {"/Apply as Filter/... _or Selected", NULL, GTK_MENU_FUNC(match_selected_ptree_cb),
959                        MATCH_SELECTED_OR|MATCH_SELECTED_APPLY_NOW, NULL, NULL,},
960     {"/Apply as Filter/... a_nd not Selected", NULL, GTK_MENU_FUNC(match_selected_ptree_cb),
961                        MATCH_SELECTED_AND_NOT|MATCH_SELECTED_APPLY_NOW, NULL, NULL,},
962     {"/Apply as Filter/... o_r not Selected", NULL, GTK_MENU_FUNC(match_selected_ptree_cb),
963                        MATCH_SELECTED_OR_NOT|MATCH_SELECTED_APPLY_NOW, NULL, NULL,},
964
965     {"/Prepare a Filter", NULL, NULL, 0, "<Branch>", NULL,},
966     {"/Prepare a Filter/_Selected", NULL, GTK_MENU_FUNC(match_selected_ptree_cb),
967                        MATCH_SELECTED_REPLACE, NULL, NULL,},
968     {"/Prepare a Filter/_Not Selected", NULL, GTK_MENU_FUNC(match_selected_ptree_cb),
969                        MATCH_SELECTED_NOT, NULL, NULL,},
970     {"/Prepare a Filter/... _and Selected", NULL, GTK_MENU_FUNC(match_selected_ptree_cb),
971                        MATCH_SELECTED_AND, NULL, NULL,},
972     {"/Prepare a Filter/... _or Selected", NULL, GTK_MENU_FUNC(match_selected_ptree_cb),
973                        MATCH_SELECTED_OR, NULL, NULL,},
974     {"/Prepare a Filter/... a_nd not Selected", NULL, GTK_MENU_FUNC(match_selected_ptree_cb),
975                        MATCH_SELECTED_AND_NOT, NULL, NULL,},
976     {"/Prepare a Filter/... o_r not Selected", NULL, GTK_MENU_FUNC(match_selected_ptree_cb),
977                        MATCH_SELECTED_OR_NOT, NULL, NULL,},
978
979     {"/Colorize with Filter", NULL, NULL, 0, "<Branch>", NULL,},
980     {"/Colorize with Filter/Color 1", NULL, GTK_MENU_FUNC(colorize_selected_ptree_cb), 1, "<StockItem>", WIRESHARK_STOCK_COLOR1,},
981     {"/Colorize with Filter/Color 2", NULL, GTK_MENU_FUNC(colorize_selected_ptree_cb), 2, "<StockItem>", WIRESHARK_STOCK_COLOR2,},
982     {"/Colorize with Filter/Color 3", NULL, GTK_MENU_FUNC(colorize_selected_ptree_cb), 3, "<StockItem>", WIRESHARK_STOCK_COLOR3,},
983     {"/Colorize with Filter/Color 4", NULL, GTK_MENU_FUNC(colorize_selected_ptree_cb), 4, "<StockItem>", WIRESHARK_STOCK_COLOR4,},
984     {"/Colorize with Filter/Color 5", NULL, GTK_MENU_FUNC(colorize_selected_ptree_cb), 5, "<StockItem>", WIRESHARK_STOCK_COLOR5,},
985     {"/Colorize with Filter/Color 6", NULL, GTK_MENU_FUNC(colorize_selected_ptree_cb), 6, "<StockItem>", WIRESHARK_STOCK_COLOR6,},
986     {"/Colorize with Filter/Color 7", NULL, GTK_MENU_FUNC(colorize_selected_ptree_cb), 7, "<StockItem>", WIRESHARK_STOCK_COLOR7,},
987     {"/Colorize with Filter/Color 8", NULL, GTK_MENU_FUNC(colorize_selected_ptree_cb), 8, "<StockItem>", WIRESHARK_STOCK_COLOR8,},
988     {"/Colorize with Filter/Color 9", NULL, GTK_MENU_FUNC(colorize_selected_ptree_cb), 9, "<StockItem>", WIRESHARK_STOCK_COLOR9,},
989     {"/Colorize with Filter/Color 10", NULL, GTK_MENU_FUNC(colorize_selected_ptree_cb), 10, "<StockItem>", WIRESHARK_STOCK_COLOR0,},
990     {"/Colorize with Filter/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
991     {"/Colorize with Filter/New Coloring Rule...", NULL, GTK_MENU_FUNC(colorize_selected_ptree_cb), 0, "<StockItem>", GTK_STOCK_SELECT_COLOR,},
992
993     {"/Follow TCP Stream", NULL, GTK_MENU_FUNC(follow_tcp_stream_cb),
994                        0, NULL, NULL,},
995     {"/Follow UDP Stream", NULL, GTK_MENU_FUNC(follow_udp_stream_cb),
996                        0, NULL, NULL,},
997     {"/Follow SSL Stream", NULL, GTK_MENU_FUNC(follow_ssl_stream_cb),
998                        0, NULL, NULL,},
999
1000     {"/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
1001
1002     {"/Copy", NULL, NULL, 0, "<Branch>", NULL,},
1003     {"/Copy/Description", NULL, GTK_MENU_FUNC(copy_selected_plist_cb), 0, NULL, NULL,},
1004     {"/Copy/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
1005     {"/Copy/As Filter", NULL, GTK_MENU_FUNC(match_selected_ptree_cb), MATCH_SELECTED_REPLACE|MATCH_SELECTED_COPY_ONLY, NULL, NULL,},
1006     {"/Copy/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
1007     {"/Copy/Bytes (Offset Hex Text)", NULL, GTK_MENU_FUNC(copy_hex_cb), CD_ALLINFO | CD_FLAGS_SELECTEDONLY, NULL, NULL,},
1008     {"/Copy/Bytes (Offset Hex)", NULL, GTK_MENU_FUNC(copy_hex_cb), CD_HEXCOLUMNS | CD_FLAGS_SELECTEDONLY, NULL, NULL,},
1009     {"/Copy/Bytes (Printable Text Only)", NULL, GTK_MENU_FUNC(copy_hex_cb), CD_TEXTONLY | CD_FLAGS_SELECTEDONLY, NULL, NULL,},
1010     {"/Copy/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
1011     {"/Copy/Bytes (Hex Stream)", NULL, GTK_MENU_FUNC(copy_hex_cb), CD_HEX | CD_FLAGS_SELECTEDONLY, NULL, NULL,},
1012     {"/Copy/Bytes (Binary Stream)", NULL, GTK_MENU_FUNC(copy_hex_cb), CD_BINARY | CD_FLAGS_SELECTEDONLY, NULL, NULL,},
1013
1014     {"/Export Selected Packet Bytes...", NULL, GTK_MENU_FUNC(savehex_cb),
1015                        0, NULL, NULL,},
1016
1017     {"/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
1018
1019     {"/Wiki Protocol Page", NULL, GTK_MENU_FUNC(selected_ptree_info_cb),
1020                        0, "<StockItem>", WIRESHARK_STOCK_WIKI,},
1021     {"/Filter Field Reference", NULL, GTK_MENU_FUNC(selected_ptree_ref_cb),
1022                        0, "<StockItem>", WIRESHARK_STOCK_INTERNET,},
1023     {"/Protocol Preferences", NULL, NULL, 0, NULL, NULL,},
1024     {"/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
1025     {"/Decode As...", NULL, GTK_MENU_FUNC(decode_as_cb), 0, "<StockItem>", WIRESHARK_STOCK_DECODE_AS,},
1026     {"/Disable Protocol...", NULL, GTK_MENU_FUNC(proto_disable_cb), 0, "<StockItem>", WIRESHARK_STOCK_CHECKBOX,},
1027     {"/_Resolve Name", NULL, GTK_MENU_FUNC(resolve_name_cb), 0, NULL, NULL,},
1028     {"/_Go to Corresponding Packet", NULL, GTK_MENU_FUNC(goto_framenum_cb), 0, NULL, NULL,}
1029 };
1030
1031
1032 static int initialize = TRUE;
1033 static GtkItemFactory *main_menu_factory = NULL;
1034 static GtkItemFactory *packet_list_menu_factory = NULL;
1035 static GtkItemFactory *tree_view_menu_factory = NULL;
1036 static GtkItemFactory *hexdump_menu_factory = NULL;
1037
1038 static GSList *popup_menu_list = NULL;
1039
1040 static GtkAccelGroup *grp;
1041
1042 GtkWidget *
1043 main_menu_new(GtkAccelGroup ** table) {
1044     GtkWidget *menubar;
1045 #ifdef HAVE_IGE_MAC_INTEGRATION
1046     GtkWidget *quit_item, *about_item, *preferences_item;
1047     IgeMacMenuGroup *group;
1048 #endif
1049
1050     grp = gtk_accel_group_new();
1051
1052     if (initialize)
1053         menus_init();
1054
1055     menubar = main_menu_factory->widget;
1056
1057 #ifdef HAVE_IGE_MAC_INTEGRATION
1058     if(prefs.gui_macosx_style) {
1059         ige_mac_menu_set_menu_bar(GTK_MENU_SHELL(menubar));
1060         ige_mac_menu_set_global_key_handler_enabled(TRUE);
1061
1062         /* Create menu items to populate the application menu with.  We have to
1063          * do this because we are still using the old GtkItemFactory API for
1064          * the main menu. */
1065         group = ige_mac_menu_add_app_menu_group();
1066         about_item = gtk_menu_item_new_with_label("About");
1067         g_signal_connect(about_item, "activate", G_CALLBACK(about_wireshark_cb),
1068                          NULL);
1069         ige_mac_menu_add_app_menu_item(group, GTK_MENU_ITEM(about_item), NULL);
1070
1071         group = ige_mac_menu_add_app_menu_group();
1072         preferences_item = gtk_menu_item_new_with_label("Preferences");
1073         g_signal_connect(preferences_item, "activate", G_CALLBACK(prefs_cb),
1074                          NULL);
1075         ige_mac_menu_add_app_menu_item(group, GTK_MENU_ITEM(preferences_item),
1076                                        NULL);
1077     }
1078
1079     /* The quit item in the application menu shows up whenever ige mac
1080      * integration is enabled, even if the OS X UI style in Wireshark isn't
1081      * turned on. */
1082     quit_item = gtk_menu_item_new_with_label("Quit");
1083     g_signal_connect(quit_item, "activate", G_CALLBACK(file_quit_cmd_cb),
1084                      NULL);
1085     ige_mac_menu_set_quit_menu_item(GTK_MENU_ITEM(quit_item));
1086 #endif
1087
1088     if (table)
1089         *table = grp;
1090
1091     return menubar;
1092 }
1093
1094
1095 void menu_dissector_filter_cb(  GtkWidget *widget _U_,
1096                                 gpointer callback_data,
1097                                 guint callback_action _U_)
1098 {
1099     dissector_filter_t      *filter_entry = callback_data;
1100     GtkWidget                   *filter_te;
1101     const char              *buf;    
1102
1103
1104     filter_te = g_object_get_data(G_OBJECT(popup_menu_object), E_DFILTER_TE_KEY);
1105
1106     /* XXX - this gets the packet_info of the last dissected packet, */
1107     /* which is not necessarily the last selected packet */
1108     /* e.g. "Update list of packets in real time" won't work correct */
1109     buf = filter_entry->build_filter_string(&cfile.edt->pi);
1110
1111         gtk_entry_set_text(GTK_ENTRY(filter_te), buf);
1112
1113         /* Run the display filter so it goes in effect - even if it's the
1114            same as the previous display filter. */
1115         main_filter_packets(&cfile, buf, TRUE);
1116
1117     g_free( (void *) buf);
1118 }
1119
1120 gboolean menu_dissector_filter_spe_cb(frame_data *fd _U_, epan_dissect_t *edt, gpointer callback_data) {
1121     dissector_filter_t *filter_entry = callback_data;
1122
1123     /* XXX - this gets the packet_info of the last dissected packet, */
1124     /* which is not necessarily the last selected packet */
1125     /* e.g. "Update list of packets in real time" won't work correct */
1126     return (edt != NULL) ? filter_entry->is_filter_valid(&edt->pi) : FALSE;
1127 }
1128
1129 void menu_dissector_filter(void) {
1130     GList *list_entry = dissector_filter_list;
1131     dissector_filter_t *filter_entry;
1132
1133     while(list_entry != NULL) {
1134         filter_entry = list_entry->data;
1135
1136         register_stat_menu_item(filter_entry->name, REGISTER_ANALYZE_GROUP_CONVERSATION_FILTER,
1137             menu_dissector_filter_cb,
1138             menu_dissector_filter_spe_cb,
1139             NULL /* selected_tree_row_enabled */,
1140             filter_entry);
1141
1142         list_entry = g_list_next(list_entry);
1143     }
1144 }
1145
1146
1147 static void
1148 menus_init(void) {
1149   if (initialize) {
1150     initialize = FALSE;
1151
1152     /* popup */
1153     packet_list_menu_factory = gtk_item_factory_new(GTK_TYPE_MENU, "<main>", NULL);
1154     popup_menu_object = gtk_menu_new();
1155     gtk_item_factory_create_items_ac(packet_list_menu_factory, sizeof(packet_list_menu_items)/sizeof(packet_list_menu_items[0]), packet_list_menu_items, popup_menu_object, 2);
1156     g_object_set_data(G_OBJECT(popup_menu_object), PM_PACKET_LIST_KEY,
1157                     packet_list_menu_factory->widget);
1158     popup_menu_list = g_slist_append((GSList *)popup_menu_list, packet_list_menu_factory);
1159
1160     tree_view_menu_factory = gtk_item_factory_new(GTK_TYPE_MENU, "<main>", NULL);
1161     gtk_item_factory_create_items_ac(tree_view_menu_factory, sizeof(tree_view_menu_items)/sizeof(tree_view_menu_items[0]), tree_view_menu_items, popup_menu_object, 2);
1162     g_object_set_data(G_OBJECT(popup_menu_object), PM_TREE_VIEW_KEY,
1163                     tree_view_menu_factory->widget);
1164     popup_menu_list = g_slist_append((GSList *)popup_menu_list, tree_view_menu_factory);
1165
1166     hexdump_menu_factory = gtk_item_factory_new(GTK_TYPE_MENU, "<main>", NULL);
1167     g_object_set_data(G_OBJECT(popup_menu_object), PM_HEXDUMP_KEY,
1168                     hexdump_menu_factory->widget);
1169     popup_menu_list = g_slist_append((GSList *)popup_menu_list, hexdump_menu_factory);
1170     /* main */
1171     main_menu_factory = gtk_item_factory_new(GTK_TYPE_MENU_BAR, "<main>", grp);
1172     gtk_item_factory_create_items_ac(main_menu_factory, nmenu_items, menu_items, NULL, 2);
1173
1174     menu_dissector_filter();
1175     merge_all_tap_menus(tap_menu_tree_root);
1176
1177     /* Initialize enabled/disabled state of menu items */
1178     set_menus_for_capture_file(NULL);
1179 #if 0
1180     /* Un-#if this when we actually implement Cut/Copy/Paste.
1181        Then make sure you enable them when they can be done. */
1182     set_menu_sensitivity(main_menu_factory, "/Edit/Cut", FALSE);
1183     set_menu_sensitivity(main_menu_factory, "/Edit/Copy", FALSE);
1184     set_menu_sensitivity(main_menu_factory, "/Edit/Paste", FALSE);
1185 #endif
1186
1187     set_menus_for_captured_packets(FALSE);
1188     set_menus_for_selected_packet(&cfile);
1189     set_menus_for_selected_tree_row(&cfile);
1190     set_menus_for_capture_in_progress(FALSE);
1191     set_menus_for_file_set(/* dialog */TRUE, /* previous file */ FALSE, /* next_file */ FALSE);
1192
1193     /* init with an empty recent files list */
1194     clear_menu_recent_capture_file_cmd_cb(NULL, NULL);
1195
1196   }
1197 }
1198
1199
1200 static gint tap_menu_item_add_compare(gconstpointer a, gconstpointer b)
1201 {
1202     return strcmp(
1203         ((const menu_item_t *) a)->name,
1204         ((const menu_item_t *) b)->name);
1205 }
1206
1207
1208 /* add a menuitem below the current node */
1209 static GList * tap_menu_item_add(
1210     char *name,
1211     gint group,
1212     const char *stock_id,
1213     GtkItemFactoryCallback callback,
1214     gboolean (*selected_packet_enabled)(frame_data *, epan_dissect_t *, gpointer callback_data),
1215     gboolean (*selected_tree_row_enabled)(field_info *, gpointer callback_data),
1216     gpointer callback_data,
1217     GList *curnode)
1218 {
1219     menu_item_t *curr;
1220     menu_item_t *child;
1221
1222
1223     child = g_malloc(sizeof (menu_item_t));
1224     child->name             = name;
1225     child->group            = group;
1226     child->stock_id         = stock_id;
1227     child->callback         = callback;
1228     child->selected_packet_enabled = selected_packet_enabled;
1229     child->selected_tree_row_enabled = selected_tree_row_enabled;
1230     child->callback_data    = callback_data;
1231     child->enabled          = FALSE;
1232     child->children         = NULL;
1233
1234     /* insert the new child node into the parent */
1235     curr = curnode->data;
1236     curr->children = g_list_insert_sorted(curr->children, child, tap_menu_item_add_compare);
1237
1238     /* return the new node */
1239     /* XXX: improve this */
1240     return g_list_find(curr->children, child);
1241 }
1242
1243 /*
1244  * Add a new menu item for a tap.
1245  * This must be called after we've created the main menu, so it can't
1246  * be called from the routine that registers taps - we have to introduce
1247  * another per-tap registration routine.
1248  *
1249  * "callback" gets called when the menu item is selected; it should do
1250  * the work of creating the tap window.
1251  *
1252  * "selected_packet_enabled" gets called by "set_menus_for_selected_packet()";
1253  * it's passed a Boolean that's TRUE if a packet is selected and FALSE
1254  * otherwise, and should return TRUE if the tap will work now (which
1255  * might depend on whether a packet is selected and, if one is, on the
1256  * packet) and FALSE if not.
1257  *
1258  * "selected_tree_row_enabled" gets called by
1259  * "set_menus_for_selected_tree_row()"; it's passed a Boolean that's TRUE if
1260  * a protocol tree row is selected and FALSE otherwise, and should return
1261  * TRUE if the tap will work now (which might depend on whether a tree row
1262  * is selected and, if one is, on the tree row) and FALSE if not.
1263  */
1264 void
1265 register_stat_menu_item_stock(
1266     const char *name,
1267     register_stat_group_t group,
1268     const char *stock_id,
1269     GtkItemFactoryCallback callback,
1270     gboolean (*selected_packet_enabled)(frame_data *, epan_dissect_t *, gpointer callback_data),
1271     gboolean (*selected_tree_row_enabled)(field_info *, gpointer callback_data),
1272     gpointer callback_data)
1273 {
1274     /*static const char toolspath[] = "/Statistics/";*/
1275     const char *toolspath;
1276     const char *p;
1277     char *menupath;
1278     size_t menupathlen;
1279     menu_item_t *child;
1280     GList *curnode;
1281     GList *childnode;
1282
1283     /*
1284      * The menu path must be relative.
1285      */
1286     g_assert(*name != '/');
1287
1288     switch(group) {
1289     case(REGISTER_STAT_GROUP_GENERIC): toolspath = "/Statistics/"; break;
1290     case(REGISTER_STAT_GROUP_CONVERSATION_LIST): toolspath = "/Statistics/_Conversation List/"; break;
1291     case(REGISTER_STAT_GROUP_ENDPOINT_LIST): toolspath = "/Statistics/_Endpoint List/"; break;
1292     case(REGISTER_STAT_GROUP_RESPONSE_TIME): toolspath = "/Statistics/Service _Response Time/"; break;
1293     case(REGISTER_STAT_GROUP_UNSORTED): toolspath = "/Statistics/"; break;
1294     case(REGISTER_ANALYZE_GROUP_UNSORTED): toolspath = "/Analyze/"; break;
1295     case(REGISTER_ANALYZE_GROUP_CONVERSATION_FILTER): toolspath = "/Analyze/Conversation Filter/"; break;
1296     case(REGISTER_STAT_GROUP_TELEPHONY): toolspath = "/Telephony/"; break;
1297     case(REGISTER_TOOLS_GROUP_UNSORTED): toolspath = "/Tools/"; break;
1298     default:
1299         g_assert(!"no such menu group");
1300         toolspath = NULL;
1301     }
1302
1303     /* add the (empty) root node, if not already done */
1304     if(tap_menu_tree_root == NULL) {
1305         child = g_malloc0(sizeof (menu_item_t));
1306         tap_menu_tree_root = g_list_append(NULL, child);
1307     }
1308
1309     /*
1310      * Create any submenus required.
1311      */
1312     curnode = tap_menu_tree_root;
1313     p = name;
1314     while ((p = strchr(p, '/')) != NULL) {
1315         /*
1316          * OK, everything between "name" and "p" is
1317          * a menu relative subtree into which the menu item
1318          * will be placed.
1319          *
1320          * Construct the absolute path name of that subtree.
1321          */
1322         menupathlen = strlen(toolspath) + 1 + (p - name);
1323         menupath = g_malloc(menupathlen);
1324         g_strlcpy(menupath, toolspath, menupathlen);
1325         g_strlcat(menupath, name, menupathlen);
1326
1327         /*
1328          * Does there exist an entry with that path at this
1329          * level of the Analyze menu tree?
1330          */
1331         child = curnode->data;
1332         for (childnode = child->children; childnode != NULL; childnode = childnode->next) {
1333             child = childnode->data;
1334             if (strcmp(child->name, menupath) == 0)
1335                 break;
1336         }
1337         if (childnode == NULL) {
1338             /*
1339              * No.  Create such an item as a subtree, and
1340              * add it to the Tools menu tree.
1341              */
1342             childnode = tap_menu_item_add(
1343                 menupath, group, "", NULL, NULL ,NULL, NULL, curnode);
1344         } else {
1345             /*
1346              * Yes.  We don't need this "menupath" any longer.
1347              */
1348             g_free(menupath);
1349         }
1350         curnode = childnode;
1351
1352         /*
1353          * Skip over the '/' we found.
1354          */
1355         p++;
1356     }
1357
1358     /*
1359      * Construct the main menu path for the menu item.
1360      */
1361     menupathlen = strlen(toolspath) + 1 + strlen(name);
1362     menupath = g_malloc(menupathlen);
1363     g_strlcpy(menupath, toolspath, menupathlen);
1364     g_strlcat(menupath, name, menupathlen);
1365
1366     /*
1367      * Construct an item factory entry for the item, and add it to
1368      * the main menu.
1369      */
1370     tap_menu_item_add(
1371         menupath, group, stock_id, callback,
1372         selected_packet_enabled, selected_tree_row_enabled,
1373         callback_data, curnode);
1374 }
1375
1376
1377 void
1378 register_stat_menu_item(
1379     const char *name,
1380     register_stat_group_t group,
1381     GtkItemFactoryCallback callback,
1382     gboolean (*selected_packet_enabled)(frame_data *, epan_dissect_t *, gpointer callback_data),
1383     gboolean (*selected_tree_row_enabled)(field_info *, gpointer callback_data),
1384     gpointer callback_data)
1385 {
1386     register_stat_menu_item_stock(
1387         name,
1388         group,
1389         NULL,
1390         callback,
1391         selected_packet_enabled,
1392         selected_tree_row_enabled,
1393         callback_data);
1394 }
1395
1396 static guint merge_tap_menus_layered(GList *node, gint group) {
1397     GtkItemFactoryEntry *entry;
1398     GList       *child;
1399     guint       added = 0;
1400     menu_item_t *node_data = node->data;
1401
1402     /*
1403      * Is this a leaf node or an interior node?
1404      */
1405     if (node_data->children == NULL) {
1406         /*
1407          * It's a leaf node.
1408          */
1409
1410         /*
1411          * The root node doesn't correspond to a menu tree item; it
1412          * has a null name pointer.
1413          */
1414         if (node_data->name != NULL && group == node_data->group) {
1415             entry = g_malloc0(sizeof (GtkItemFactoryEntry));
1416             entry->path = node_data->name;
1417             entry->callback = node_data->callback;
1418             switch(group) {
1419             case(REGISTER_STAT_GROUP_UNSORTED):
1420                 break;
1421             case(REGISTER_STAT_GROUP_GENERIC):
1422                 break;
1423             case(REGISTER_STAT_GROUP_CONVERSATION_LIST):
1424                 entry->item_type = "<StockItem>";
1425                 entry->extra_data = WIRESHARK_STOCK_CONVERSATIONS;
1426                 break;
1427             case(REGISTER_STAT_GROUP_ENDPOINT_LIST):
1428                 entry->item_type = "<StockItem>";
1429                 entry->extra_data = WIRESHARK_STOCK_ENDPOINTS;
1430                 break;
1431             case(REGISTER_STAT_GROUP_RESPONSE_TIME):
1432                 entry->item_type = "<StockItem>";
1433                 entry->extra_data = WIRESHARK_STOCK_TIME;
1434                 break;
1435             case(REGISTER_STAT_GROUP_TELEPHONY):
1436                 break;
1437             case(REGISTER_ANALYZE_GROUP_UNSORTED):
1438                 break;
1439             case(REGISTER_ANALYZE_GROUP_CONVERSATION_FILTER):
1440                 break;
1441             case(REGISTER_TOOLS_GROUP_UNSORTED):
1442                 break;
1443             default:
1444                 g_assert_not_reached();
1445             }
1446             if(node_data->stock_id!= NULL) {
1447                 entry->item_type = "<StockItem>";
1448                 entry->extra_data = node_data->stock_id;
1449             }
1450             gtk_item_factory_create_item(main_menu_factory, entry, node_data->callback_data, /* callback_type */ 2);
1451             set_menu_sensitivity(main_menu_factory, node_data->name, FALSE); /* no capture file yet */
1452             added++;
1453             g_free(entry);
1454         }
1455     } else {
1456         /*
1457          * It's an interior node; call
1458          * "merge_tap_menus_layered()" on all its children
1459          */
1460
1461         /*
1462          * The root node doesn't correspond to a menu tree item; it
1463          * has a null name pointer.
1464          */
1465         if (node_data->name != NULL && group == node_data->group) {
1466             entry = g_malloc0(sizeof (GtkItemFactoryEntry));
1467             entry->path = node_data->name;
1468             entry->item_type = "<Branch>";
1469             gtk_item_factory_create_item(main_menu_factory, entry,
1470                 NULL, 2);
1471             set_menu_sensitivity(main_menu_factory, node_data->name,
1472                 FALSE);    /* no children yet */
1473             added++;
1474             g_free(entry);
1475         }
1476
1477         for (child = node_data->children; child != NULL; child =
1478             child->next) {
1479             added += merge_tap_menus_layered(child, group);
1480         }
1481     }
1482
1483     return added;
1484 }
1485
1486
1487 void merge_all_tap_menus(GList *node) {
1488     GtkItemFactoryEntry *sep_entry;
1489
1490     sep_entry = g_malloc0(sizeof (GtkItemFactoryEntry));
1491     sep_entry->item_type = "<Separator>";
1492     sep_entry->path = "/Statistics/";
1493
1494     /*
1495      * merge only the menu items of the specific group,
1496      * and then append a seperator
1497      */
1498     if (merge_tap_menus_layered(node, REGISTER_STAT_GROUP_GENERIC)) {
1499         gtk_item_factory_create_item(main_menu_factory, sep_entry, NULL, 2);
1500     }
1501     if (merge_tap_menus_layered(node, REGISTER_STAT_GROUP_CONVERSATION_LIST)) {
1502         /*gtk_item_factory_create_item(main_menu_factory, sep_entry, NULL, 2);*/
1503     }
1504     if (merge_tap_menus_layered(node, REGISTER_STAT_GROUP_ENDPOINT_LIST)) {
1505         /*gtk_item_factory_create_item(main_menu_factory, sep_entry, NULL, 2);*/
1506     }
1507     if (merge_tap_menus_layered(node, REGISTER_STAT_GROUP_RESPONSE_TIME)) {
1508         gtk_item_factory_create_item(main_menu_factory, sep_entry, NULL, 2);
1509     }
1510     if (merge_tap_menus_layered(node, REGISTER_STAT_GROUP_TELEPHONY)) {
1511         /*gtk_item_factory_create_item(main_menu_factory, sep_entry, NULL, 2);*/
1512     }
1513     if (merge_tap_menus_layered(node, REGISTER_STAT_GROUP_UNSORTED)) {
1514         /*gtk_item_factory_create_item(main_menu_factory, sep_entry, NULL, 2);*/
1515     }
1516     if (merge_tap_menus_layered(node, REGISTER_ANALYZE_GROUP_UNSORTED)) {
1517         sep_entry->path = "/Analyze/";
1518         /*gtk_item_factory_create_item(main_menu_factory, sep_entry, NULL, 2);*/
1519     }
1520     if (merge_tap_menus_layered(node, REGISTER_ANALYZE_GROUP_CONVERSATION_FILTER)) {
1521         sep_entry->path = "/Analyze/Conversation Filter/";
1522         /*gtk_item_factory_create_item(main_menu_factory, sep_entry, NULL, 2);*/
1523     }
1524     if (merge_tap_menus_layered(node, REGISTER_TOOLS_GROUP_UNSORTED)) {
1525         /*gtk_item_factory_create_item(main_menu_factory, sep_entry, NULL, 2);*/
1526     }
1527 }
1528
1529
1530
1531 /*
1532  * Enable/disable menu sensitivity.
1533  */
1534 static void
1535 set_menu_sensitivity(GtkItemFactory *ifactory, const gchar *path, gint val)
1536 {
1537   GSList *menu_list;
1538   GtkWidget *menu_item;
1539   gchar *dup;
1540   gchar *dest;
1541
1542
1543   /* the underscore character regularly confuses things, as it will prevent finding
1544    * the menu_item, so it has to be removed first */
1545   dup = g_strdup(path);
1546   dest = dup;
1547   while(*path) {
1548       if (*path != '_') {
1549         *dest = *path;
1550         dest++;
1551       }
1552       path++;
1553   }
1554   *dest = '\0';
1555
1556   if (ifactory == NULL) {
1557     /*
1558      * Do it for all pop-up menus.
1559      */
1560     for (menu_list = popup_menu_list; menu_list != NULL;
1561          menu_list = g_slist_next(menu_list))
1562       set_menu_sensitivity(menu_list->data, dup, val);
1563   } else {
1564     /*
1565      * Do it for that particular menu.
1566      */
1567     if ((menu_item = gtk_item_factory_get_widget(ifactory, dup)) != NULL) {
1568       if (GTK_IS_MENU(menu_item)) {
1569         /*
1570          * "dup" refers to a submenu; "gtk_item_factory_get_widget()"
1571          * gets the menu, not the item that, when selected, pops up
1572          * the submenu.
1573          *
1574          * We have to change the latter item's sensitivity, so that
1575          * it shows up normally if sensitive and grayed-out if
1576          * insensitive.
1577          */
1578         menu_item = gtk_menu_get_attach_widget(GTK_MENU(menu_item));
1579       }
1580       gtk_widget_set_sensitive(menu_item, val);
1581     } else{
1582       /* be sure this menu item *is* existing */
1583       g_assert_not_reached();
1584     }
1585   }
1586
1587   g_free(dup);
1588 }
1589
1590 static void
1591 set_menu_object_data_meat(GtkItemFactory *ifactory, const gchar *path, const gchar *key, gpointer data)
1592 {
1593         GtkWidget *menu = NULL;
1594
1595         if ((menu = gtk_item_factory_get_widget(ifactory, path)) != NULL)
1596                 g_object_set_data(G_OBJECT(menu), key, data);
1597 }
1598
1599 void
1600 set_menu_object_data (const gchar *path, const gchar *key, gpointer data) {
1601   GSList *menu_list = popup_menu_list;
1602   gchar *shortpath = strrchr(path, '/');
1603
1604   set_menu_object_data_meat(main_menu_factory, path, key, data);
1605   while (menu_list != NULL) {
1606     set_menu_object_data_meat(menu_list->data, shortpath, key, data);
1607     set_menu_object_data_meat(menu_list->data, path, key, data);
1608     menu_list = g_slist_next(menu_list);
1609   }
1610 }
1611
1612
1613 /* Recently used capture files submenu:
1614  * Submenu containing the recently used capture files.
1615  * The capture filenames are always kept with the absolute path, to be independant
1616  * of the current path.
1617  * They are only stored inside the labels of the submenu (no separate list). */
1618
1619 #define MENU_RECENT_FILES_PATH "/File/Open Recent"
1620 #define MENU_RECENT_FILES_KEY "Recent File Name"
1621
1622
1623
1624 static void
1625 update_menu_recent_capture_file1(GtkWidget *widget, gpointer cnt) {
1626     gchar *widget_cf_name;
1627
1628     widget_cf_name = g_object_get_data(G_OBJECT(widget), MENU_RECENT_FILES_KEY);
1629
1630     /* if this menu item is a file, count it */
1631     if (widget_cf_name) {
1632         (*(guint *)cnt)++;
1633         main_welcome_add_recent_capture_files(widget_cf_name);
1634     }
1635 }
1636
1637
1638
1639 /* update the menu */
1640 static void
1641 update_menu_recent_capture_file(GtkWidget *submenu_recent_files) {
1642     guint cnt = 0;
1643
1644
1645     main_welcome_reset_recent_capture_files();
1646
1647     gtk_container_foreach(GTK_CONTAINER(submenu_recent_files),
1648                 update_menu_recent_capture_file1, &cnt);
1649
1650     /* make parent menu item sensitive only, if we have any valid files in the list */
1651     set_menu_sensitivity(main_menu_factory, MENU_RECENT_FILES_PATH, cnt);
1652 }
1653
1654
1655
1656 /* remove the capture filename from the "Recent Files" menu */
1657 static void
1658 remove_menu_recent_capture_filename(gchar *cf_name) {
1659     GtkWidget *submenu_recent_files;
1660     GList* child_list;
1661     GList* child_list_item;
1662         GtkWidget *menu_item_child;
1663         gchar     *menu_item_cf_name;
1664     
1665
1666     /* get the submenu container item */
1667     submenu_recent_files = gtk_item_factory_get_widget(main_menu_factory, MENU_RECENT_FILES_PATH);
1668
1669     /* find the corresponding menu item to be removed */
1670     child_list = gtk_container_get_children(GTK_CONTAINER(submenu_recent_files));
1671     child_list_item = child_list;
1672     while(child_list_item) {
1673             menu_item_child = (GTK_BIN(child_list_item->data))->child;
1674             gtk_label_get(GTK_LABEL(menu_item_child), &menu_item_cf_name);
1675         if(strcmp(menu_item_cf_name, cf_name) == 0) {
1676             /* XXX: is this all we need to do, to free the menu item and its label?
1677                The reference count of widget will go to 0, so it'll be freed;
1678                will that free the label? */
1679             gtk_container_remove(GTK_CONTAINER(submenu_recent_files), child_list_item->data);
1680         }
1681         child_list_item = g_list_next(child_list_item);
1682     }
1683     g_list_free(child_list);
1684
1685     update_menu_recent_capture_file(submenu_recent_files);
1686 }
1687
1688
1689 /* remove the capture filename from the "Recent Files" menu */
1690 static void
1691 remove_menu_recent_capture_file(GtkWidget *widget, gpointer unused _U_) {
1692     GtkWidget *submenu_recent_files;
1693     gchar *widget_cf_name;
1694
1695
1696     widget_cf_name = g_object_get_data(G_OBJECT(widget), MENU_RECENT_FILES_KEY);
1697     g_free(widget_cf_name);
1698
1699     /* get the submenu container item */
1700     submenu_recent_files = gtk_item_factory_get_widget(main_menu_factory, MENU_RECENT_FILES_PATH);
1701
1702     /* XXX: is this all we need to do, to free the menu item and its label?
1703        The reference count of widget will go to 0, so it'll be freed;
1704        will that free the label? */
1705     gtk_container_remove(GTK_CONTAINER(submenu_recent_files), widget);
1706 }
1707
1708
1709 /* callback, if the user pushed the <Clear> menu item */
1710 static void
1711 clear_menu_recent_capture_file_cmd_cb(GtkWidget *w _U_, gpointer unused _U_) {
1712     GtkWidget *submenu_recent_files;
1713
1714
1715     submenu_recent_files = gtk_item_factory_get_widget(main_menu_factory, MENU_RECENT_FILES_PATH);
1716
1717     gtk_container_foreach(GTK_CONTAINER(submenu_recent_files),
1718                 remove_menu_recent_capture_file, NULL);
1719
1720     update_menu_recent_capture_file(submenu_recent_files);
1721 }
1722
1723
1724 /* Open a file by it's name
1725    (Beware: will not ask to close existing capture file!) */
1726 void
1727 menu_open_filename(gchar *cf_name)
1728 {
1729         GtkWidget *submenu_recent_files;
1730         int       err;
1731
1732         submenu_recent_files = gtk_item_factory_get_widget(main_menu_factory, MENU_RECENT_FILES_PATH);
1733
1734         /* open and read the capture file (this will close an existing file) */
1735         if (cf_open(&cfile, cf_name, FALSE, &err) == CF_OK) {
1736                 cf_read(&cfile);
1737         } else {
1738                 /* the capture file isn't existing any longer, remove menu item */
1739                 /* XXX: ask user to remove item, it's maybe only a temporary problem */
1740                 remove_menu_recent_capture_filename(cf_name);
1741         }
1742
1743         update_menu_recent_capture_file(submenu_recent_files);
1744 }
1745
1746
1747 /* callback, if the user pushed a recent file submenu item */
1748 void
1749 menu_open_recent_file_cmd(GtkWidget *w)
1750 {
1751         GtkWidget *submenu_recent_files;
1752         GtkWidget *menu_item_child;
1753         gchar     *cf_name;
1754         int       err;
1755
1756         submenu_recent_files = gtk_item_factory_get_widget(main_menu_factory, MENU_RECENT_FILES_PATH);
1757
1758         /* get capture filename from the menu item label */
1759         menu_item_child = (GTK_BIN(w))->child;
1760         gtk_label_get(GTK_LABEL(menu_item_child), &cf_name);
1761
1762         /* open and read the capture file (this will close an existing file) */
1763         if (cf_open(&cfile, cf_name, FALSE, &err) == CF_OK) {
1764                 cf_read(&cfile);
1765         } else {
1766                 /* the capture file isn't existing any longer, remove menu item */
1767                 /* XXX: ask user to remove item, it's maybe only a temporary problem */
1768                 remove_menu_recent_capture_file(w, NULL);
1769         }
1770
1771         update_menu_recent_capture_file(submenu_recent_files);
1772 }
1773
1774 static void menu_open_recent_file_answered_cb(gpointer dialog _U_, gint btn, gpointer data)
1775 {
1776     switch(btn) {
1777     case(ESD_BTN_YES):
1778         /* save file first */
1779         file_save_as_cmd(after_save_open_recent_file, data);
1780         break;
1781     case(ESD_BTN_NO):
1782         cf_close(&cfile);
1783         menu_open_recent_file_cmd(data);
1784         break;
1785     case(ESD_BTN_CANCEL):
1786         break;
1787     default:
1788         g_assert_not_reached();
1789     }
1790 }
1791
1792 static void
1793 menu_open_recent_file_cmd_cb(GtkWidget *widget, gpointer data _U_) {
1794   gpointer  dialog;
1795
1796
1797   if((cfile.state != FILE_CLOSED) && !cfile.user_saved && prefs.gui_ask_unsaved) {
1798     /* user didn't saved his current file, ask him */
1799     dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_YES_NO_CANCEL,
1800                 "%sSave capture file before opening a new one?%s\n\n"
1801                 "If you open a new capture file without saving, your current capture data will be discarded.",
1802                 simple_dialog_primary_start(), simple_dialog_primary_end());
1803     simple_dialog_set_cb(dialog, menu_open_recent_file_answered_cb, widget);
1804   } else {
1805     /* unchanged file */
1806     menu_open_recent_file_cmd(widget);
1807   }
1808 }
1809
1810 /* add the capture filename (with an absolute path) to the "Recent Files" menu */
1811 static void
1812 add_menu_recent_capture_file_absolute(gchar *cf_name) {
1813         GtkWidget *submenu_recent_files;
1814         GList *menu_item_list;
1815         GList *li;
1816         gchar *widget_cf_name;
1817         gchar *normalized_cf_name;
1818         GtkWidget *menu_item;
1819         guint cnt;
1820
1821
1822
1823         normalized_cf_name = g_strdup(cf_name);
1824 #ifdef _WIN32
1825         /* replace all slashes by backslashes */
1826         g_strdelimit(normalized_cf_name, "/", '\\');
1827 #endif
1828
1829         /* get the submenu container item */
1830         submenu_recent_files = gtk_item_factory_get_widget(main_menu_factory, MENU_RECENT_FILES_PATH);
1831
1832         /* convert container to a GList */
1833         menu_item_list = gtk_container_get_children(GTK_CONTAINER(submenu_recent_files));
1834
1835         /* iterate through list items of menu_item_list,
1836          * removing special items, a maybe duplicate entry and every item above count_max */
1837         cnt = 1;
1838         for (li = g_list_first(menu_item_list); li; li = li->next, cnt++) {
1839                 /* get capture filename */
1840                 menu_item = GTK_WIDGET(li->data);
1841                 widget_cf_name = g_object_get_data(G_OBJECT(menu_item), MENU_RECENT_FILES_KEY);
1842
1843                 /* if this element string is one of our special items (seperator, ...) or
1844                  * already in the list or
1845                  * this element is above maximum count (too old), remove it */
1846                 if (!widget_cf_name ||
1847 #ifdef _WIN32
1848                     /* do a case insensitive compare on win32 */
1849                     g_ascii_strncasecmp(widget_cf_name, normalized_cf_name, 1000) == 0 ||
1850 #else   /* _WIN32 */
1851                     /* do a case sensitive compare on unix */
1852                     strncmp(widget_cf_name, normalized_cf_name, 1000) == 0 ||
1853 #endif
1854                     cnt >= prefs.gui_recent_files_count_max) {
1855                         remove_menu_recent_capture_file(li->data, NULL);
1856                         cnt--;
1857                 }
1858         }
1859
1860         g_list_free(menu_item_list);
1861
1862         /* add new item at latest position */
1863         menu_item = gtk_menu_item_new_with_label(normalized_cf_name);
1864         g_object_set_data(G_OBJECT(menu_item), MENU_RECENT_FILES_KEY, normalized_cf_name);
1865         gtk_menu_shell_prepend (GTK_MENU_SHELL(submenu_recent_files), menu_item);
1866         g_signal_connect_swapped(GTK_OBJECT(menu_item), "activate",
1867                 G_CALLBACK(menu_open_recent_file_cmd_cb), (GtkObject *) menu_item);
1868         gtk_widget_show (menu_item);
1869
1870         /* add seperator at last position */
1871         menu_item = gtk_menu_item_new();
1872         gtk_menu_append (GTK_MENU(submenu_recent_files), menu_item);
1873         gtk_widget_show (menu_item);
1874
1875         /* add new "clear list" item at last position */
1876         menu_item = gtk_image_menu_item_new_from_stock(GTK_STOCK_CLEAR, NULL);
1877         gtk_menu_append (GTK_MENU(submenu_recent_files), menu_item);
1878         g_signal_connect_swapped(GTK_OBJECT(menu_item), "activate",
1879                 G_CALLBACK(clear_menu_recent_capture_file_cmd_cb), (GtkObject *) menu_item);
1880         gtk_widget_show (menu_item);
1881
1882         update_menu_recent_capture_file(submenu_recent_files);
1883 }
1884
1885
1886 /* add the capture filename to the "Recent Files" menu */
1887 /* (will change nothing, if this filename is already in the menu) */
1888 /*
1889  * XXX - We might want to call SHAddToRecentDocs under Windows 7:
1890  * http://stackoverflow.com/questions/437212/how-do-you-register-a-most-recently-used-list-with-windows-in-preparation-for-win
1891  */
1892 void
1893 add_menu_recent_capture_file(gchar *cf_name) {
1894         gchar *curr;
1895         gchar *absolute;
1896
1897
1898         /* if this filename is an absolute path, we can use it directly */
1899         if (g_path_is_absolute(cf_name)) {
1900                 add_menu_recent_capture_file_absolute(cf_name);
1901                 return;
1902         }
1903
1904         /* this filename is not an absolute path, prepend the current dir */
1905         curr = g_get_current_dir();
1906         absolute = g_strdup_printf("%s%s%s", curr, G_DIR_SEPARATOR_S, cf_name);
1907         add_menu_recent_capture_file_absolute(absolute);
1908         g_free(curr);
1909         g_free(absolute);
1910 }
1911
1912
1913 /* write all capture filenames of the menu to the user's recent file */
1914 void
1915 menu_recent_file_write_all(FILE *rf) {
1916     GtkWidget   *submenu_recent_files;
1917     GList       *children;
1918     GList       *child;
1919     gchar       *cf_name;
1920
1921
1922     submenu_recent_files = gtk_item_factory_get_widget(main_menu_factory, MENU_RECENT_FILES_PATH);
1923
1924     /* we have to iterate backwards through the children's list,
1925      * so we get the latest item last in the file.
1926      * (don't use gtk_container_foreach() here, it will return the wrong iteration order) */
1927     children = gtk_container_get_children(GTK_CONTAINER(submenu_recent_files));
1928     child = g_list_last(children);
1929     while(child != NULL) {
1930         /* get capture filename from the menu item label */
1931         cf_name = g_object_get_data(G_OBJECT(child->data), MENU_RECENT_FILES_KEY);
1932         if (cf_name) {
1933             if(u3_active())
1934                 fprintf (rf, RECENT_KEY_CAPTURE_FILE ": %s\n", u3_contract_device_path(cf_name));
1935             else
1936                 fprintf (rf, RECENT_KEY_CAPTURE_FILE ": %s\n", cf_name);
1937         }
1938
1939         child = g_list_previous(child);
1940     }
1941
1942     g_list_free(children);
1943 }
1944
1945
1946 static void
1947 show_hide_cb(GtkWidget *w, gpointer data _U_, gint action)
1948 {
1949
1950     /* save current setting in recent */
1951     switch(action) {
1952         case(SHOW_HIDE_MAIN_TOOLBAR):
1953         recent.main_toolbar_show = GTK_CHECK_MENU_ITEM(w)->active;
1954         break;
1955         case(SHOW_HIDE_FILTER_TOOLBAR):
1956         recent.filter_toolbar_show = GTK_CHECK_MENU_ITEM(w)->active;
1957         break;
1958 #ifdef HAVE_AIRPCAP
1959         case(SHOW_HIDE_AIRPCAP_TOOLBAR):
1960         recent.airpcap_toolbar_show = GTK_CHECK_MENU_ITEM(w)->active;
1961         break;
1962 #endif
1963         case(SHOW_HIDE_STATUSBAR):
1964         recent.statusbar_show = GTK_CHECK_MENU_ITEM(w)->active;
1965         break;
1966         case(SHOW_HIDE_PACKET_LIST):
1967         recent.packet_list_show = GTK_CHECK_MENU_ITEM(w)->active;
1968         break;
1969         case(SHOW_HIDE_TREE_VIEW):
1970         recent.tree_view_show = GTK_CHECK_MENU_ITEM(w)->active;
1971         break;
1972         case(SHOW_HIDE_BYTE_VIEW):
1973         recent.byte_view_show = GTK_CHECK_MENU_ITEM(w)->active;
1974         break;
1975         default:
1976             g_assert_not_reached();
1977     }
1978
1979     main_widgets_show_or_hide();
1980 }
1981
1982
1983 static void
1984 timestamp_format_cb(GtkWidget *w _U_, gpointer d _U_, gint action)
1985 {
1986     if (recent.gui_time_format != action) {
1987         timestamp_set_type(action);
1988         recent.gui_time_format = action;
1989         cf_change_time_formats(&cfile);
1990     }
1991 }
1992
1993
1994 static void
1995 timestamp_precision_cb(GtkWidget *w _U_, gpointer d _U_, gint action)
1996 {
1997     if (recent.gui_time_precision != action) {
1998         /* the actual precision will be set in cf_change_time_formats() below */
1999         if (action == TS_PREC_AUTO) {
2000             timestamp_set_precision(TS_PREC_AUTO_SEC);
2001         } else {
2002             timestamp_set_precision(action);
2003         }
2004         recent.gui_time_precision  = action;
2005         cf_change_time_formats(&cfile);
2006     }
2007 }
2008
2009
2010 void
2011 menu_name_resolution_changed(void)
2012 {
2013     GtkWidget *menu = NULL;
2014
2015     menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Name Resolution/Enable for MAC Layer");
2016     gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), g_resolv_flags & RESOLV_MAC);
2017
2018     menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Name Resolution/Enable for Network Layer");
2019     gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), g_resolv_flags & RESOLV_NETWORK);
2020
2021     menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Name Resolution/Enable for Transport Layer");
2022     gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), g_resolv_flags & RESOLV_TRANSPORT);
2023 }
2024
2025 static void
2026 name_resolution_cb(GtkWidget *w, gpointer d _U_, gint action)
2027 {
2028     if (GTK_CHECK_MENU_ITEM(w)->active) {
2029         g_resolv_flags |= action;
2030     } else {
2031         g_resolv_flags &= ~action;
2032     }
2033 }
2034
2035 #ifdef HAVE_LIBPCAP
2036 void
2037 menu_auto_scroll_live_changed(gboolean auto_scroll_live_in) {
2038     GtkWidget *menu;
2039
2040
2041     /* tell menu about it */
2042     menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Auto Scroll in Live Capture");
2043     if( ((gboolean) GTK_CHECK_MENU_ITEM(menu)->active) != auto_scroll_live_in) {
2044         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), auto_scroll_live_in);
2045     }
2046
2047     /* tell toolbar about it */
2048     toolbar_auto_scroll_live_changed(auto_scroll_live_in);
2049
2050     /* change auto scroll */
2051     if(auto_scroll_live_in != auto_scroll_live) {
2052         auto_scroll_live  = auto_scroll_live_in;
2053     }
2054 }
2055
2056 static void
2057 auto_scroll_live_cb(GtkWidget *w _U_, gpointer d _U_)
2058 {
2059     menu_auto_scroll_live_changed(GTK_CHECK_MENU_ITEM(w)->active);
2060 }
2061 #endif
2062
2063
2064 void
2065 menu_colorize_changed(gboolean packet_list_colorize) {
2066     GtkWidget *menu;
2067
2068
2069     /* tell menu about it */
2070     menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Colorize Packet List");
2071     if( ((gboolean) GTK_CHECK_MENU_ITEM(menu)->active) != packet_list_colorize) {
2072         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), packet_list_colorize);
2073     }
2074
2075     /* tell toolbar about it */
2076     toolbar_colorize_changed(packet_list_colorize);
2077
2078     /* change colorization */
2079     if(packet_list_colorize != recent.packet_list_colorize) {
2080         recent.packet_list_colorize = packet_list_colorize;
2081         color_filters_enable(packet_list_colorize);
2082         cf_colorize_packets(&cfile);
2083     }
2084 }
2085
2086 static void
2087 colorize_cb(GtkWidget *w, gpointer d _U_)
2088 {
2089     menu_colorize_changed(GTK_CHECK_MENU_ITEM(w)->active);
2090 }
2091
2092
2093 /* the recent file read has finished, update the menu corresponding */
2094 void
2095 menu_recent_read_finished(void) {
2096     GtkWidget *menu = NULL;
2097
2098     menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Main Toolbar");
2099     gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), recent.main_toolbar_show);
2100
2101     menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Filter Toolbar");
2102     gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), recent.filter_toolbar_show);
2103
2104 #ifdef HAVE_AIRPCAP
2105     menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Wireless Toolbar");
2106     gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), recent.airpcap_toolbar_show);
2107 #endif
2108
2109     menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Statusbar");
2110     gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), recent.statusbar_show);
2111
2112     menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Packet List");
2113     gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), recent.packet_list_show);
2114
2115     menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Packet Details");
2116     gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), recent.tree_view_show);
2117
2118     menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Packet Bytes");
2119     gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), recent.byte_view_show);
2120
2121     menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Colorize Packet List");
2122     gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), recent.packet_list_colorize);
2123
2124     menu_name_resolution_changed();
2125
2126 #ifdef HAVE_LIBPCAP
2127     menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Auto Scroll in Live Capture");
2128     gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), auto_scroll_live);
2129 #endif
2130
2131     main_widgets_rearrange();
2132
2133     /* don't change the time format, if we had a command line value */
2134     if (timestamp_get_type() != TS_NOT_SET) {
2135         recent.gui_time_format = timestamp_get_type();
2136     }
2137
2138     switch(recent.gui_time_format) {
2139     case(TS_ABSOLUTE_WITH_DATE):
2140         menu = gtk_item_factory_get_widget(main_menu_factory,
2141             "/View/Time Display Format/Date and Time of Day:   1970-01-01 01:02:03.123456");
2142         /* set_active will not trigger the callback when activating an active item! */
2143         recent.gui_time_format = -1;
2144         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), FALSE);
2145         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), TRUE);
2146         break;
2147     case(TS_ABSOLUTE):
2148         menu = gtk_item_factory_get_widget(main_menu_factory,
2149             "/View/Time Display Format/Time of Day:   01:02:03.123456");
2150         /* set_active will not trigger the callback when activating an active item! */
2151         recent.gui_time_format = -1;
2152         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), TRUE);
2153         break;
2154     case(TS_RELATIVE):
2155         menu = gtk_item_factory_get_widget(main_menu_factory,
2156             "/View/Time Display Format/Seconds Since Beginning of Capture:   123.123456");
2157         recent.gui_time_format = -1;
2158         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), TRUE);
2159         break;
2160     case(TS_DELTA):
2161         menu = gtk_item_factory_get_widget(main_menu_factory,
2162             "/View/Time Display Format/Seconds Since Previous Captured Packet:   1.123456");
2163         recent.gui_time_format = -1;
2164         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), TRUE);
2165         break;
2166     case(TS_DELTA_DIS):
2167         menu = gtk_item_factory_get_widget(main_menu_factory,
2168             "/View/Time Display Format/Seconds Since Previous Displayed Packet:   1.123456");
2169         recent.gui_time_format = -1;
2170         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), TRUE);
2171         break;
2172     case(TS_EPOCH):
2173         menu = gtk_item_factory_get_widget(main_menu_factory,
2174             "/View/Time Display Format/Seconds Since Epoch (1970-01-01):   1234567890.123456");
2175         recent.gui_time_format = -1;
2176         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), TRUE);
2177         break;
2178     default:
2179         g_assert_not_reached();
2180     }
2181
2182     switch(recent.gui_time_precision) {
2183     case(TS_PREC_AUTO):
2184         menu = gtk_item_factory_get_widget(main_menu_factory,
2185             "/View/Time Display Format/Automatic (File Format Precision)");
2186         /* set_active will not trigger the callback when activating an active item! */
2187         recent.gui_time_precision = -1;
2188         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), FALSE);
2189         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), TRUE);
2190         break;
2191     case(TS_PREC_FIXED_SEC):
2192         menu = gtk_item_factory_get_widget(main_menu_factory,
2193             "/View/Time Display Format/Seconds:   0");
2194         recent.gui_time_precision = -1;
2195         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), TRUE);
2196         break;
2197     case(TS_PREC_FIXED_DSEC):
2198         menu = gtk_item_factory_get_widget(main_menu_factory,
2199             "/View/Time Display Format/Deciseconds:   0.1");
2200         recent.gui_time_precision = -1;
2201         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), TRUE);
2202         break;
2203     case(TS_PREC_FIXED_CSEC):
2204         menu = gtk_item_factory_get_widget(main_menu_factory,
2205             "/View/Time Display Format/Centiseconds:   0.12");
2206         recent.gui_time_precision = -1;
2207         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), TRUE);
2208         break;
2209     case(TS_PREC_FIXED_MSEC):
2210         menu = gtk_item_factory_get_widget(main_menu_factory,
2211             "/View/Time Display Format/Milliseconds:   0.123");
2212         recent.gui_time_precision = -1;
2213         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), TRUE);
2214         break;
2215     case(TS_PREC_FIXED_USEC):
2216         menu = gtk_item_factory_get_widget(main_menu_factory,
2217             "/View/Time Display Format/Microseconds:   0.123456");
2218         recent.gui_time_precision = -1;
2219         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), TRUE);
2220         break;
2221     case(TS_PREC_FIXED_NSEC):
2222         menu = gtk_item_factory_get_widget(main_menu_factory,
2223             "/View/Time Display Format/Nanoseconds:   0.123456789");
2224         recent.gui_time_precision = -1;
2225         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), TRUE);
2226         break;
2227     default:
2228         g_assert_not_reached();
2229     }
2230
2231     menu_colorize_changed(recent.packet_list_colorize);
2232 }
2233
2234
2235 gint
2236 popup_menu_handler(GtkWidget *widget, GdkEvent *event, gpointer data)
2237 {
2238     GtkWidget *menu = (GtkWidget *)data;
2239     GdkEventButton *event_button = NULL;
2240     gint row, column;
2241
2242     if(widget == NULL || event == NULL || data == NULL) {
2243         return FALSE;
2244     }
2245
2246     /*
2247      * If we ever want to make the menu differ based on what row
2248      * and/or column we're above, we'd use "eth_clist_get_selection_info()"
2249      * to find the row and column number for the coordinates; a CTree is,
2250      * I guess, like a CList with one column(?) and the expander widget
2251      * as a pixmap.
2252      */
2253     /* Check if we are on packet_list object */
2254     if (widget == g_object_get_data(G_OBJECT(popup_menu_object), E_MPACKET_LIST_KEY) &&
2255         ((GdkEventButton *)event)->button != 1) {
2256         if (packet_list_get_event_row_column(widget, (GdkEventButton *)event,
2257                                              &row, &column)) {
2258             g_object_set_data(G_OBJECT(popup_menu_object), E_MPACKET_LIST_ROW_KEY,
2259                             GINT_TO_POINTER(row));
2260             g_object_set_data(G_OBJECT(popup_menu_object), E_MPACKET_LIST_COL_KEY,
2261                             GINT_TO_POINTER(column));
2262             packet_list_set_selected_row(row);
2263         }
2264     }
2265
2266     /* Check if we are on tree_view object */
2267     if (widget == tree_view) {
2268         tree_view_select(widget, (GdkEventButton *) event);
2269     }
2270
2271     /* Check if we are on byte_view object */
2272     if(widget == get_notebook_bv_ptr(byte_nb_ptr)) {
2273         byte_view_select(widget, (GdkEventButton *) event);
2274     }
2275
2276     /* context menu handler */
2277     if(event->type == GDK_BUTTON_PRESS) {
2278         event_button = (GdkEventButton *) event;
2279
2280         /* To qoute the "Gdk Event Structures" doc:
2281          * "Normally button 1 is the left mouse button, 2 is the middle button, and 3 is the right button" */
2282         if(event_button->button == 3) {
2283             /* No popup window in the byte view */
2284             if(widget != get_notebook_bv_ptr(byte_nb_ptr)) {
2285                 gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL,
2286                                event_button->button,
2287                                event_button->time);
2288             }
2289             g_signal_stop_emission_by_name(widget, "button_press_event");
2290             return TRUE;
2291         }
2292     }
2293     /* GDK_2BUTTON_PRESS is a doubleclick -> expand/collapse tree row */
2294     /* GTK version 1 seems to be doing this automatically */
2295     if (widget == tree_view && event->type == GDK_2BUTTON_PRESS) {
2296         GtkTreePath      *path;
2297
2298         if (gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(widget),
2299                                           (gint) (((GdkEventButton *)event)->x),
2300                                           (gint) (((GdkEventButton *)event)->y),
2301                                           &path, NULL, NULL, NULL))
2302         {
2303             if (gtk_tree_view_row_expanded(GTK_TREE_VIEW(widget), path))
2304                 gtk_tree_view_collapse_row(GTK_TREE_VIEW(widget), path);
2305             else
2306                 gtk_tree_view_expand_row(GTK_TREE_VIEW(widget), path,
2307                                          FALSE);
2308             gtk_tree_path_free(path);
2309         }
2310     }
2311     return FALSE;
2312 }
2313
2314 /* Enable or disable menu items based on whether you have a capture file
2315    you've finished reading and, if you have one, whether it's been saved
2316    and whether it could be saved except by copying the raw packet data. */
2317 void
2318 set_menus_for_capture_file(capture_file *cf)
2319 {
2320   if (cf == NULL) {
2321     /* We have no capture file */
2322     set_menu_sensitivity(main_menu_factory, "/File/Merge...", FALSE);
2323     set_menu_sensitivity(main_menu_factory, "/File/Close", FALSE);
2324     set_menu_sensitivity(main_menu_factory, "/File/Save", FALSE);
2325     set_menu_sensitivity(main_menu_factory, "/File/Save As...", FALSE);
2326     set_menu_sensitivity(main_menu_factory, "/File/Export", FALSE);
2327     set_menu_sensitivity(main_menu_factory, "/View/Reload", FALSE);
2328     set_toolbar_for_capture_file(FALSE);
2329     set_toolbar_for_unsaved_capture_file(FALSE);
2330   } else {
2331     set_menu_sensitivity(main_menu_factory, "/File/Merge...", TRUE);
2332     set_menu_sensitivity(main_menu_factory, "/File/Close", TRUE);
2333     set_menu_sensitivity(main_menu_factory, "/File/Save", !cf->user_saved);
2334     /*
2335      * "Save As..." works only if we can write the file out in at least
2336      * one format (so we can save the whole file or just a subset) or
2337      * if we have an unsaved capture (so writing the whole file out
2338      * with a raw data copy makes sense).
2339      */
2340     set_menu_sensitivity(main_menu_factory, "/File/Save As...",
2341         cf_can_save_as(cf) || !cf->user_saved);
2342     set_menu_sensitivity(main_menu_factory, "/File/Export", TRUE);
2343     set_menu_sensitivity(main_menu_factory, "/View/Reload", TRUE);
2344     set_toolbar_for_unsaved_capture_file(!cf->user_saved);
2345     set_toolbar_for_capture_file(TRUE);
2346   }
2347 }
2348
2349 /* Enable or disable menu items based on whether there's a capture in
2350    progress. */
2351 void
2352 set_menus_for_capture_in_progress(gboolean capture_in_progress)
2353 {
2354   set_menu_sensitivity(main_menu_factory, "/File/Open...",
2355       !capture_in_progress);
2356   set_menu_sensitivity(main_menu_factory, "/File/Open Recent",
2357       !capture_in_progress);
2358   set_menu_sensitivity(main_menu_factory, "/File/Export",
2359        capture_in_progress);
2360 #ifdef HAVE_LIBPCAP
2361   set_menu_sensitivity(main_menu_factory, "/Capture/Options...",
2362       !capture_in_progress);
2363   set_menu_sensitivity(main_menu_factory, "/Capture/Start",
2364       !capture_in_progress);
2365   set_menu_sensitivity(main_menu_factory, "/Capture/Stop",
2366       capture_in_progress);
2367   set_menu_sensitivity(main_menu_factory, "/Capture/Restart",
2368       capture_in_progress);
2369   set_toolbar_for_capture_in_progress(capture_in_progress);
2370
2371   set_capture_if_dialog_for_capture_in_progress(capture_in_progress);
2372 #endif /* HAVE_LIBPCAP */
2373 }
2374
2375 /* Enable or disable menu items based on whether you have some captured
2376    packets. */
2377 static gboolean
2378 walk_menu_tree_for_captured_packets(GList *node,
2379     gboolean have_captured_packets)
2380 {
2381         gboolean    is_enabled;
2382         GList       *child;
2383         menu_item_t *node_data = node->data;
2384
2385         /*
2386          * Is this a leaf node or an interior node?
2387          */
2388         if (node_data->children == NULL) {
2389                 /*
2390                  * It's a leaf node.
2391                  *
2392                  * If it has no "selected_packet_enabled()" or
2393                  * "selected_tree_row_enabled()" routines, we enable
2394                  * it.  This allows tap windows to be popped up even
2395                  * if you have no capture file; this is done to let
2396                  * the user pop up multiple tap windows before reading
2397                  * in a capture file, so that they can be processed in
2398                  * parallel while the capture file is being read rather
2399                  * than one at at time as you pop up the windows, and to
2400                  * let the user pop up tap windows before starting an
2401                  * "Update list of packets in real time" capture, so that
2402                  * the statistics can be displayed while the capture is
2403                  * in progress.
2404                  *
2405                  * If it has either of those routines, we disable it for
2406                  * now - as long as, when a capture is first available,
2407                  * we don't get called after a packet or tree row is
2408                  * selected, that's OK.
2409                  * XXX - that should be done better.
2410                  */
2411                 if (node_data->selected_packet_enabled == NULL &&
2412                     node_data->selected_tree_row_enabled == NULL)
2413                         node_data->enabled = TRUE;
2414                 else
2415                         node_data->enabled = FALSE;
2416         } else {
2417                 /*
2418                  * It's an interior node; call
2419                  * "walk_menu_tree_for_captured_packets()" on all its
2420                  * children and, if any of them are enabled, enable
2421                  * this node, otherwise disable it.
2422                  *
2423                  * XXX - should we just leave all interior nodes enabled?
2424                  * Which is a better UI choice?
2425                  */
2426                 is_enabled = FALSE;
2427                 for (child = node_data->children; child != NULL; child =
2428                     child->next) {
2429                         if (walk_menu_tree_for_captured_packets(child,
2430                             have_captured_packets))
2431                                 is_enabled = TRUE;
2432                 }
2433                 node_data->enabled = is_enabled;
2434         }
2435
2436         /*
2437          * The root node doesn't correspond to a menu tree item; it
2438          * has a null name pointer.
2439          */
2440         if (node_data->name != NULL) {
2441                 set_menu_sensitivity(main_menu_factory, node_data->name,
2442                     node_data->enabled);
2443         }
2444         return node_data->enabled;
2445 }
2446
2447 void
2448 set_menus_for_captured_packets(gboolean have_captured_packets)
2449 {
2450   set_menu_sensitivity(main_menu_factory, "/File/Print...",
2451       have_captured_packets);
2452   set_menu_sensitivity(packet_list_menu_factory, "/Print...",
2453       have_captured_packets);
2454   set_menu_sensitivity(main_menu_factory, "/Edit/Find Packet...",
2455       have_captured_packets);
2456   set_menu_sensitivity(main_menu_factory, "/Edit/Find Next",
2457       have_captured_packets);
2458   set_menu_sensitivity(main_menu_factory, "/Edit/Find Previous",
2459       have_captured_packets);
2460   set_menu_sensitivity(main_menu_factory, "/View/Zoom In",
2461       have_captured_packets);
2462   set_menu_sensitivity(main_menu_factory, "/View/Zoom Out",
2463       have_captured_packets);
2464   set_menu_sensitivity(main_menu_factory, "/View/Normal Size",
2465       have_captured_packets);
2466   set_menu_sensitivity(main_menu_factory, "/Go/Go to Packet...",
2467       have_captured_packets);
2468   set_menu_sensitivity(main_menu_factory, "/Go/Previous Packet",
2469       have_captured_packets);
2470   set_menu_sensitivity(main_menu_factory, "/Go/Next Packet",
2471       have_captured_packets);
2472   set_menu_sensitivity(main_menu_factory, "/Go/First Packet",
2473       have_captured_packets);
2474   set_menu_sensitivity(main_menu_factory, "/Go/Last Packet",
2475       have_captured_packets);
2476   set_menu_sensitivity(main_menu_factory, "/Statistics/Summary",
2477       have_captured_packets);
2478   set_menu_sensitivity(main_menu_factory, "/Statistics/Protocol Hierarchy",
2479       have_captured_packets);
2480
2481   walk_menu_tree_for_captured_packets(tap_menu_tree_root,
2482       have_captured_packets);
2483   set_toolbar_for_captured_packets(have_captured_packets);
2484 }
2485
2486 /* Enable or disable menu items based on whether a packet is selected and,
2487    if so, on the properties of the packet. */
2488 static gboolean
2489 walk_menu_tree_for_selected_packet(GList *node, frame_data *fd,
2490     epan_dissect_t *edt)
2491 {
2492         gboolean is_enabled;
2493         GList *child;
2494         menu_item_t *node_data = node->data;
2495
2496         /*
2497          * Is this a leaf node or an interior node?
2498          */
2499         if (node_data->children == NULL) {
2500                 /*
2501                  * It's a leaf node.
2502                  *
2503                  * If it has no "selected_packet_enabled()" routine,
2504                  * leave its enabled/disabled status alone - it
2505                  * doesn't depend on whether we have a packet selected
2506                  * or not or on the selected packet.
2507                  *
2508                  * If it has a "selected_packet_enabled()" routine,
2509                  * call it and set the item's enabled/disabled status
2510                  * based on its return value.
2511                  */
2512                 if (node_data->selected_packet_enabled != NULL)
2513                         node_data->enabled = node_data->selected_packet_enabled(fd, edt, node_data->callback_data);
2514         } else {
2515                 /*
2516                  * It's an interior node; call
2517                  * "walk_menu_tree_for_selected_packet()" on all its
2518                  * children and, if any of them are enabled, enable
2519                  * this node, otherwise disable it.
2520                  *
2521                  * XXX - should we just leave all interior nodes enabled?
2522                  * Which is a better UI choice?
2523                  */
2524                 is_enabled = FALSE;
2525                 for (child = node_data->children; child != NULL; child =
2526                     child->next) {
2527                         if (walk_menu_tree_for_selected_packet(child, fd, edt))
2528                                 is_enabled = TRUE;
2529                 }
2530                 node_data->enabled = is_enabled;
2531         }
2532
2533         /*
2534          * The root node doesn't correspond to a menu tree item; it
2535          * has a null name pointer.
2536          */
2537         if (node_data->name != NULL) {
2538                 set_menu_sensitivity(main_menu_factory, node_data->name,
2539                     node_data->enabled);
2540         }
2541         return node_data->enabled;
2542 }
2543
2544 gboolean
2545 packet_is_ssl(epan_dissect_t* edt)
2546 {
2547   GPtrArray* array;
2548   int ssl_id;
2549   gboolean is_ssl;
2550
2551   if (!edt || !edt->tree)
2552       return FALSE;
2553   ssl_id = proto_get_id_by_filter_name("ssl");
2554   if (ssl_id < 0)
2555       return FALSE;
2556   array = proto_find_finfo(edt->tree, ssl_id);
2557   is_ssl = (array->len > 0) ? TRUE : FALSE;
2558   g_ptr_array_free(array, FALSE);
2559   return is_ssl;
2560 }
2561
2562 void
2563 set_menus_for_selected_packet(capture_file *cf)
2564 {
2565   gboolean is_ssl = packet_is_ssl(cf->edt);
2566   set_menu_sensitivity(main_menu_factory, "/Edit/Mark Packet (toggle)",
2567       cf->current_frame != NULL);
2568   set_menu_sensitivity(packet_list_menu_factory, "/Mark Packet (toggle)",
2569       cf->current_frame != NULL);
2570   set_menu_sensitivity(main_menu_factory, "/Edit/Find Next Mark",
2571       cf->current_frame != NULL);
2572   set_menu_sensitivity(main_menu_factory, "/Edit/Find Previous Mark",
2573       cf->current_frame != NULL);
2574   set_menu_sensitivity(main_menu_factory, "/Edit/Mark All Packets",
2575       cf->current_frame != NULL);
2576   set_menu_sensitivity(main_menu_factory, "/Edit/Unmark All Packets",
2577       cf->current_frame != NULL);
2578   set_menu_sensitivity(main_menu_factory, "/Edit/Set Time Reference (toggle)",
2579       cf->current_frame != NULL);
2580   set_menu_sensitivity(packet_list_menu_factory, "/Set Time Reference (toggle)",
2581       cf->current_frame != NULL);
2582   set_menu_sensitivity(main_menu_factory, "/Edit/Find Next Reference",
2583       cf->current_frame != NULL);
2584   set_menu_sensitivity(main_menu_factory, "/Edit/Find Previous Reference",
2585       cf->current_frame != NULL);
2586   set_menu_sensitivity(main_menu_factory, "/View/Resize All Columns",
2587       cf->current_frame != NULL);
2588   set_menu_sensitivity(main_menu_factory, "/View/Collapse All",
2589       cf->current_frame != NULL);
2590   set_menu_sensitivity(tree_view_menu_factory, "/Collapse All",
2591       cf->current_frame != NULL);
2592   set_menu_sensitivity(main_menu_factory, "/View/Expand All",
2593       cf->current_frame != NULL);
2594   set_menu_sensitivity(tree_view_menu_factory, "/Expand All",
2595       cf->current_frame != NULL);
2596   set_menu_sensitivity(main_menu_factory, "/View/Colorize Conversation",
2597       cf->current_frame != NULL);
2598   set_menu_sensitivity(main_menu_factory, "/View/Reset Coloring 1-10",
2599       tmp_color_filters_used());
2600   set_menu_sensitivity(main_menu_factory, "/View/Show Packet in New Window",
2601       cf->current_frame != NULL);
2602   set_menu_sensitivity(packet_list_menu_factory, "/Show Packet in New Window",
2603       cf->current_frame != NULL);
2604   set_menu_sensitivity(packet_list_menu_factory, "/SCTP",
2605       cf->current_frame != NULL ? (cf->edt->pi.ipproto == IP_PROTO_SCTP) : FALSE);
2606   set_menu_sensitivity(main_menu_factory, "/Analyze/Follow TCP Stream",
2607       cf->current_frame != NULL ? (cf->edt->pi.ipproto == IP_PROTO_TCP) : FALSE);
2608   set_menu_sensitivity(packet_list_menu_factory, "/Follow TCP Stream",
2609       cf->current_frame != NULL ? (cf->edt->pi.ipproto == IP_PROTO_TCP) : FALSE);
2610   set_menu_sensitivity(tree_view_menu_factory, "/Follow TCP Stream",
2611       cf->current_frame != NULL ? (cf->edt->pi.ipproto == IP_PROTO_TCP) : FALSE);
2612   set_menu_sensitivity(main_menu_factory, "/Analyze/Follow UDP Stream",
2613       cf->current_frame != NULL ? (cf->edt->pi.ipproto == IP_PROTO_UDP) : FALSE);
2614   set_menu_sensitivity(packet_list_menu_factory, "/Follow UDP Stream",
2615       cf->current_frame != NULL ? (cf->edt->pi.ipproto == IP_PROTO_UDP) : FALSE);
2616   set_menu_sensitivity(tree_view_menu_factory, "/Follow UDP Stream",
2617       cf->current_frame != NULL ? (cf->edt->pi.ipproto == IP_PROTO_UDP) : FALSE);
2618   set_menu_sensitivity(main_menu_factory, "/Analyze/Follow SSL Stream",
2619       cf->current_frame != NULL ? is_ssl : FALSE);
2620   set_menu_sensitivity(packet_list_menu_factory, "/Follow SSL Stream",
2621       cf->current_frame != NULL ? is_ssl : FALSE);
2622   set_menu_sensitivity(tree_view_menu_factory, "/Follow SSL Stream",
2623       cf->current_frame != NULL ? is_ssl : FALSE);
2624   set_menu_sensitivity(packet_list_menu_factory, "/Conversation Filter",
2625       cf->current_frame != NULL);
2626   set_menu_sensitivity(packet_list_menu_factory, "/Conversation Filter/Ethernet",
2627       cf->current_frame != NULL ? (cf->edt->pi.dl_src.type == AT_ETHER) : FALSE);
2628   set_menu_sensitivity(packet_list_menu_factory, "/Conversation Filter/IP",
2629       cf->current_frame != NULL ? ((cf->edt->pi.ethertype == ETHERTYPE_IP)||(cf->edt->pi.ethertype == ETHERTYPE_IPv6)) : FALSE);
2630   set_menu_sensitivity(packet_list_menu_factory, "/Conversation Filter/TCP",
2631       cf->current_frame != NULL ? (cf->edt->pi.ipproto == IP_PROTO_TCP) : FALSE);
2632   set_menu_sensitivity(packet_list_menu_factory, "/Conversation Filter/UDP",
2633       cf->current_frame != NULL ? (cf->edt->pi.ipproto == IP_PROTO_UDP) : FALSE);
2634   set_menu_sensitivity(packet_list_menu_factory, "/Conversation Filter/PN-CBA Server",
2635       cf->current_frame != NULL ? (cf->edt->pi.profinet_type != 0 && cf->edt->pi.profinet_type < 10) : FALSE);
2636   set_menu_sensitivity(packet_list_menu_factory, "/Colorize Conversation",
2637       cf->current_frame != NULL);
2638   set_menu_sensitivity(packet_list_menu_factory, "/Colorize Conversation/Ethernet",
2639       cf->current_frame != NULL ? (cf->edt->pi.dl_src.type == AT_ETHER) : FALSE);
2640   set_menu_sensitivity(packet_list_menu_factory, "/Colorize Conversation/IP",
2641       cf->current_frame != NULL ? ((cf->edt->pi.ethertype == ETHERTYPE_IP)||(cf->edt->pi.ethertype == ETHERTYPE_IPv6)) : FALSE);
2642   set_menu_sensitivity(packet_list_menu_factory, "/Colorize Conversation/TCP",
2643       cf->current_frame != NULL ? (cf->edt->pi.ipproto == IP_PROTO_TCP) : FALSE);
2644   set_menu_sensitivity(packet_list_menu_factory, "/Colorize Conversation/UDP",
2645       cf->current_frame != NULL ? (cf->edt->pi.ipproto == IP_PROTO_UDP) : FALSE);
2646   set_menu_sensitivity(packet_list_menu_factory, "/Colorize Conversation/PN-CBA Server",
2647       cf->current_frame != NULL ? (cf->edt->pi.profinet_type != 0 && cf->edt->pi.profinet_type < 10) : FALSE);
2648   set_menu_sensitivity(main_menu_factory, "/Analyze/Decode As...",
2649       cf->current_frame != NULL && decode_as_ok());
2650   set_menu_sensitivity(packet_list_menu_factory, "/Decode As...",
2651       cf->current_frame != NULL && decode_as_ok());
2652   set_menu_sensitivity(tree_view_menu_factory, "/Decode As...",
2653       cf->current_frame != NULL && decode_as_ok());
2654   set_menu_sensitivity(main_menu_factory, "/View/Name Resolution/Resolve Name",
2655       cf->current_frame != NULL && (g_resolv_flags & RESOLV_ALL_ADDRS) != RESOLV_ALL_ADDRS);
2656   set_menu_sensitivity(tree_view_menu_factory, "/Resolve Name",
2657       cf->current_frame != NULL && (g_resolv_flags & RESOLV_ALL_ADDRS) != RESOLV_ALL_ADDRS);
2658   set_menu_sensitivity(packet_list_menu_factory, "/Copy",
2659       cf->current_frame != NULL);
2660   set_menu_sensitivity(packet_list_menu_factory, "/Apply as Filter",
2661       cf->current_frame != NULL);
2662   set_menu_sensitivity(packet_list_menu_factory, "/Prepare a Filter",
2663       cf->current_frame != NULL);
2664   set_menu_sensitivity(main_menu_factory, "/Tools/Firewall ACL Rules",
2665       cf->current_frame != NULL);
2666
2667   walk_menu_tree_for_selected_packet(tap_menu_tree_root, cf->current_frame,
2668       cf->edt);
2669 }
2670
2671 /* Enable or disable menu items based on whether a tree row is selected
2672    and, if so, on the properties of the tree row. */
2673 static gboolean
2674 walk_menu_tree_for_selected_tree_row(GList *node, field_info *fi)
2675 {
2676         gboolean is_enabled;
2677         GList *child;
2678         menu_item_t *node_data = node->data;
2679
2680         /*
2681          * Is this a leaf node or an interior node?
2682          */
2683         if (node_data->children == NULL) {
2684                 /*
2685                  * It's a leaf node.
2686                  *
2687                  * If it has no "selected_tree_row_enabled()" routine,
2688                  * leave its enabled/disabled status alone - it
2689                  * doesn't depend on whether we have a tree row selected
2690                  * or not or on the selected tree row.
2691                  *
2692                  * If it has a "selected_tree_row_enabled()" routine,
2693                  * call it and set the item's enabled/disabled status
2694                  * based on its return value.
2695                  */
2696                 if (node_data->selected_tree_row_enabled != NULL)
2697                         node_data->enabled = node_data->selected_tree_row_enabled(fi, node_data->callback_data);
2698         } else {
2699                 /*
2700                  * It's an interior node; call
2701                  * "walk_menu_tree_for_selected_tree_row()" on all its
2702                  * children and, if any of them are enabled, enable
2703                  * this node, otherwise disable it.
2704                  *
2705                  * XXX - should we just leave all interior nodes enabled?
2706                  * Which is a better UI choice?
2707                  */
2708                 is_enabled = FALSE;
2709                 for (child = node_data->children; child != NULL; child =
2710                     child->next) {
2711                         if (walk_menu_tree_for_selected_tree_row(child, fi))
2712                                 is_enabled = TRUE;
2713                 }
2714                 node_data->enabled = is_enabled;
2715         }
2716
2717         /*
2718          * The root node doesn't correspond to a menu tree item; it
2719          * has a null name pointer.
2720          */
2721         if (node_data->name != NULL) {
2722                 set_menu_sensitivity(main_menu_factory, node_data->name,
2723                     node_data->enabled);
2724         }
2725         return node_data->enabled;
2726 }
2727
2728 static void
2729 menu_prefs_toggle_bool (GtkWidget *w, gpointer data)
2730 {
2731   gboolean *value = data;
2732   module_t *module = g_object_get_data (G_OBJECT(w), "module");
2733   
2734   module->prefs_changed = TRUE;
2735   *value = !(*value);
2736
2737   prefs_apply (module);
2738   if (!prefs.gui_use_pref_save) {
2739       prefs_main_write();
2740   }
2741   cf_redissect_packets(&cfile);
2742 }
2743
2744 static void
2745 menu_prefs_change_enum (GtkWidget *w, gpointer data)
2746 {
2747   gint *value = data;
2748   module_t *module = g_object_get_data (G_OBJECT(w), "module");
2749   gint new_value = GPOINTER_TO_INT(g_object_get_data (G_OBJECT(w), "enumval"));
2750
2751   if (*value != new_value) {
2752     module->prefs_changed = TRUE;
2753     *value = new_value;
2754
2755     prefs_apply (module);
2756     if (!prefs.gui_use_pref_save) {
2757       prefs_main_write();
2758     }
2759     cf_redissect_packets(&cfile);
2760   }
2761 }
2762
2763 static guint
2764 add_protocol_prefs_menu (pref_t *pref, gpointer data)
2765 {
2766   GtkWidget *menu_preferences;
2767   GtkWidget *menu_item, *menu_sub_item, *sub_menu;
2768   module_t *module = data;
2769   const enum_val_t *enum_valp;
2770   gchar *label;
2771
2772   switch (pref->type) {
2773   case PREF_UINT:
2774     label = g_strdup_printf ("%s: %u", pref->title, *pref->varp.uint);
2775     menu_item = gtk_menu_item_new_with_label(label);
2776     gtk_widget_set_sensitive (menu_item, FALSE);
2777     g_free (label);
2778     break;
2779   case PREF_BOOL:
2780     menu_item = gtk_check_menu_item_new_with_label(pref->title);
2781     gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM(menu_item), *pref->varp.boolp);
2782     gtk_check_menu_item_set_show_toggle (GTK_CHECK_MENU_ITEM(menu_item), TRUE);
2783     g_object_set_data (G_OBJECT(menu_item), "module", module);
2784     g_signal_connect(menu_item, "activate", G_CALLBACK(menu_prefs_toggle_bool), pref->varp.boolp);
2785     break;
2786   case PREF_ENUM:
2787     menu_item = gtk_menu_item_new_with_label(pref->title);
2788     sub_menu = gtk_menu_new();
2789     gtk_menu_item_set_submenu (GTK_MENU_ITEM(menu_item), sub_menu);
2790     enum_valp = pref->info.enum_info.enumvals;
2791     while (enum_valp->name != NULL) {
2792       menu_sub_item = gtk_check_menu_item_new_with_label(enum_valp->description);
2793       gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM(menu_sub_item), enum_valp->value == *pref->varp.enump);
2794       gtk_check_menu_item_set_show_toggle (GTK_CHECK_MENU_ITEM(menu_sub_item), TRUE);
2795       g_object_set_data (G_OBJECT(menu_sub_item), "module", module);
2796       g_object_set_data (G_OBJECT(menu_sub_item), "enumval", GINT_TO_POINTER(enum_valp->value));
2797       g_object_set (G_OBJECT(menu_sub_item), "draw-as-radio", TRUE, NULL);
2798       g_signal_connect(menu_sub_item, "activate", G_CALLBACK(menu_prefs_change_enum), pref->varp.enump);
2799       gtk_menu_append (sub_menu, menu_sub_item);
2800       gtk_widget_show (menu_sub_item);
2801       enum_valp++;
2802     }
2803     break;
2804   case PREF_STRING:
2805     label = g_strdup_printf ("%s: %s", pref->title, *pref->varp.string);
2806     menu_item = gtk_menu_item_new_with_label(label);
2807     gtk_widget_set_sensitive (menu_item, FALSE);
2808     g_free (label);
2809     break;
2810   case PREF_RANGE:
2811     label = g_strdup_printf ("%s: %s", pref->title, range_convert_range (*pref->varp.range));
2812     menu_item = gtk_menu_item_new_with_label(label);
2813     gtk_widget_set_sensitive (menu_item, FALSE);
2814     g_free (label);
2815     break;
2816   case PREF_UAT:
2817     label = g_strdup_printf ("%s...", pref->title);
2818     menu_item = gtk_menu_item_new_with_label(label);
2819     g_signal_connect (menu_item, "activate", G_CALLBACK(uat_window_cb), pref->varp.uat);
2820     g_free (label);
2821     break;
2822   case PREF_STATIC_TEXT:
2823   case PREF_OBSOLETE:
2824   default:
2825     /* Nothing to add */
2826     return 0;
2827   }
2828
2829   menu_preferences = gtk_item_factory_get_widget(tree_view_menu_factory, "/Protocol Preferences");
2830   sub_menu = gtk_menu_item_get_submenu (GTK_MENU_ITEM(menu_preferences));
2831   gtk_menu_append (sub_menu, menu_item);
2832   gtk_widget_show (menu_item);
2833
2834   return 0;
2835 }
2836
2837 static void
2838 rebuild_protocol_prefs_menu (module_t *prefs, gboolean preferences)
2839 {
2840   GtkWidget *menu_preferences, *menu_item;
2841   GtkWidget *sub_menu;
2842   gchar *label;
2843
2844   menu_preferences = gtk_item_factory_get_widget(tree_view_menu_factory, "/Protocol Preferences");
2845   
2846   if (preferences) {
2847     sub_menu = gtk_menu_new();
2848     gtk_menu_item_set_submenu (GTK_MENU_ITEM(menu_preferences), sub_menu);
2849
2850     label = g_strdup_printf ("%s Preferences...", prefs->description);
2851     menu_item = gtk_image_menu_item_new_with_label (label);
2852     gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM(menu_item), 
2853                                    gtk_image_new_from_stock(GTK_STOCK_PREFERENCES, GTK_ICON_SIZE_MENU));
2854     gtk_menu_append (sub_menu, menu_item);
2855     g_signal_connect_swapped(GTK_OBJECT(menu_item), "activate",
2856                              G_CALLBACK(properties_cb), (GtkObject *) menu_item);
2857     gtk_widget_show (menu_item);
2858     g_free (label);
2859
2860     menu_item = gtk_menu_item_new();
2861     gtk_menu_append (sub_menu, menu_item);
2862     gtk_widget_show (menu_item);
2863
2864     prefs_pref_foreach(prefs, add_protocol_prefs_menu, prefs);
2865   } else {
2866     /* No preferences, remove sub menu */
2867     gtk_menu_item_set_submenu (GTK_MENU_ITEM(menu_preferences), NULL);
2868   }
2869
2870 }
2871
2872 void
2873 set_menus_for_selected_tree_row(capture_file *cf)
2874 {
2875   gboolean properties;
2876   gint id;
2877
2878   if (cf->finfo_selected != NULL) {
2879         header_field_info *hfinfo = cf->finfo_selected->hfinfo;
2880         const char *abbrev;
2881         char *prev_abbrev;
2882
2883         if (hfinfo->parent == -1) {
2884           abbrev = hfinfo->abbrev;
2885           id = (hfinfo->type == FT_PROTOCOL) ? proto_get_id((protocol_t *)hfinfo->strings) : -1;
2886         } else {
2887           abbrev = proto_registrar_get_abbrev(hfinfo->parent);
2888           id = hfinfo->parent;
2889         }
2890         properties = prefs_is_registered_protocol(abbrev);
2891
2892         set_menu_sensitivity(main_menu_factory,
2893           "/File/Export/Selected Packet Bytes...", TRUE);
2894         set_menu_sensitivity(main_menu_factory,
2895           "/Go/Go to Corresponding Packet", hfinfo->type == FT_FRAMENUM);
2896         set_menu_sensitivity(tree_view_menu_factory,
2897           "/Go to Corresponding Packet", hfinfo->type == FT_FRAMENUM);
2898         set_menu_sensitivity(main_menu_factory, "/Edit/Copy/As Filter",
2899           proto_can_match_selected(cf->finfo_selected, cf->edt));
2900         set_menu_sensitivity(tree_view_menu_factory, "/Copy",
2901           TRUE);
2902         set_menu_sensitivity(tree_view_menu_factory, "/Copy/As Filter",
2903           proto_can_match_selected(cf->finfo_selected, cf->edt));
2904         set_menu_sensitivity(main_menu_factory, "/Analyze/Apply as Filter",
2905           proto_can_match_selected(cf->finfo_selected, cf->edt));
2906         set_menu_sensitivity(tree_view_menu_factory, "/Apply as Filter",
2907           proto_can_match_selected(cf->finfo_selected, cf->edt));
2908         set_menu_sensitivity(main_menu_factory, "/Analyze/Prepare a Filter",
2909           proto_can_match_selected(cf->finfo_selected, cf->edt));
2910         set_menu_sensitivity(tree_view_menu_factory, "/Prepare a Filter",
2911           proto_can_match_selected(cf->finfo_selected, cf->edt));
2912         set_menu_sensitivity(tree_view_menu_factory, "/Colorize with Filter",
2913           proto_can_match_selected(cf->finfo_selected, cf->edt));
2914         set_menu_sensitivity(tree_view_menu_factory, "/Protocol Preferences",
2915           properties);
2916         set_menu_sensitivity(tree_view_menu_factory, "/Disable Protocol...",
2917           (id == -1) ? FALSE : proto_can_toggle_protocol(id));
2918         set_menu_sensitivity(main_menu_factory, "/View/Expand Subtrees", cf->finfo_selected->tree_type != -1);
2919         set_menu_sensitivity(tree_view_menu_factory, "/Expand Subtrees", cf->finfo_selected->tree_type != -1);
2920         set_menu_sensitivity(tree_view_menu_factory, "/Wiki Protocol Page",
2921           TRUE);
2922         set_menu_sensitivity(tree_view_menu_factory, "/Filter Field Reference",
2923           TRUE);
2924         
2925         prev_abbrev = g_object_get_data(G_OBJECT(tree_view_menu_factory), "menu_abbrev");
2926         if (!prev_abbrev || (strcmp (prev_abbrev, abbrev) != 0)) {
2927           /* No previous protocol or protocol changed - update Protocol Preferences menu */
2928           module_t *prefs = prefs_find_module(abbrev);
2929           rebuild_protocol_prefs_menu (prefs, properties);
2930
2931           g_object_set_data(G_OBJECT(tree_view_menu_factory), "menu_abbrev", g_strdup(abbrev));
2932           if (prev_abbrev) {
2933             g_free (prev_abbrev);
2934           }
2935         }
2936   } else {
2937         set_menu_sensitivity(main_menu_factory,
2938           "/File/Export/Selected Packet Bytes...", FALSE);
2939         set_menu_sensitivity(main_menu_factory,
2940           "/Go/Go to Corresponding Packet", FALSE);
2941         set_menu_sensitivity(tree_view_menu_factory,
2942           "/Go to Corresponding Packet", FALSE);
2943         set_menu_sensitivity(main_menu_factory, "/Edit/Copy/As Filter", FALSE);
2944         set_menu_sensitivity(tree_view_menu_factory, "/Copy", FALSE);
2945         set_menu_sensitivity(main_menu_factory, "/Analyze/Apply as Filter", FALSE);
2946         set_menu_sensitivity(tree_view_menu_factory, "/Apply as Filter", FALSE);
2947         set_menu_sensitivity(main_menu_factory, "/Analyze/Prepare a Filter", FALSE);
2948         set_menu_sensitivity(tree_view_menu_factory, "/Prepare a Filter", FALSE);
2949         set_menu_sensitivity(tree_view_menu_factory, "/Colorize with Filter", FALSE);
2950         set_menu_sensitivity(tree_view_menu_factory, "/Protocol Preferences",
2951           FALSE);
2952         set_menu_sensitivity(tree_view_menu_factory, "/Disable Protocol...", FALSE);
2953         set_menu_sensitivity(main_menu_factory, "/View/Expand Subtrees", FALSE);
2954         set_menu_sensitivity(tree_view_menu_factory, "/Expand Subtrees", FALSE);
2955         set_menu_sensitivity(tree_view_menu_factory, "/Wiki Protocol Page",
2956           FALSE);
2957         set_menu_sensitivity(tree_view_menu_factory, "/Filter Field Reference",
2958           FALSE);
2959   }
2960
2961   walk_menu_tree_for_selected_tree_row(tap_menu_tree_root, cf->finfo_selected);
2962 }
2963
2964 void set_menus_for_packet_history(gboolean back_history, gboolean forward_history) {
2965
2966   set_menu_sensitivity(main_menu_factory, "/Go/Back", back_history);
2967   set_menu_sensitivity(main_menu_factory, "/Go/Forward", forward_history);
2968
2969   set_toolbar_for_packet_history(back_history, forward_history);
2970 }
2971
2972
2973 void set_menus_for_file_set(gboolean file_set, gboolean previous_file, gboolean next_file) {
2974
2975   set_menu_sensitivity(main_menu_factory, "/File/File Set/List Files", file_set);
2976   set_menu_sensitivity(main_menu_factory, "/File/File Set/Previous File", previous_file);
2977   set_menu_sensitivity(main_menu_factory, "/File/File Set/Next File", next_file);
2978 }