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