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