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