4ca981eb0c6c0628b58004d75feb55a813427e42
[obnox/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  #ifndef NEW_PACKET_LIST
631     {"/Go/Previous Packet", "<control>Up",
632                              GTK_MENU_FUNC(packet_list_prev), 0, "<StockItem>", GTK_STOCK_GO_UP,},
633     {"/Go/Next Packet", "<control>Down",
634                              GTK_MENU_FUNC(packet_list_next), 0, "<StockItem>", GTK_STOCK_GO_DOWN,},
635     {"/Go/F_irst Packet", "<control>Home",
636                              GTK_MENU_FUNC(goto_top_frame_cb), 0, "<StockItem>", GTK_STOCK_GOTO_TOP,},
637     {"/Go/_Last Packet", "<control>End",
638                              GTK_MENU_FUNC(goto_bottom_frame_cb), 0, "<StockItem>", GTK_STOCK_GOTO_BOTTOM,},
639 #endif /* NEW_PACKET_LIST */
640 #ifdef HAVE_LIBPCAP
641     {"/_Capture", NULL, NULL, 0, "<Branch>", NULL,},
642     {"/Capture/_Interfaces...", "<control>I",
643                              GTK_MENU_FUNC(capture_if_cb), 0, "<StockItem>", WIRESHARK_STOCK_CAPTURE_INTERFACES,},
644     {"/Capture/_Options...", "<control>K",
645                              GTK_MENU_FUNC(capture_prep_cb), 0, "<StockItem>", WIRESHARK_STOCK_CAPTURE_OPTIONS,},
646     {"/Capture/_Start", "<control>E",
647                              GTK_MENU_FUNC(capture_start_cb), 0, "<StockItem>", WIRESHARK_STOCK_CAPTURE_START,},
648     {"/Capture/S_top", "<control>E", GTK_MENU_FUNC(capture_stop_cb),
649                              0, "<StockItem>", WIRESHARK_STOCK_CAPTURE_STOP,},
650     {"/Capture/_Restart", "<control>R", GTK_MENU_FUNC(capture_restart_cb),
651                              0, "<StockItem>", WIRESHARK_STOCK_CAPTURE_RESTART,},
652     {"/Capture/Capture _Filters...", NULL, GTK_MENU_FUNC(cfilter_dialog_cb),
653                        0, "<StockItem>", WIRESHARK_STOCK_CAPTURE_FILTER,},
654 #endif /* HAVE_LIBPCAP */
655     {"/_Analyze", NULL, NULL, 0, "<Branch>", NULL,},
656     {"/Analyze/_Display Filters...", NULL, GTK_MENU_FUNC(dfilter_dialog_cb),
657                        0, "<StockItem>", WIRESHARK_STOCK_DISPLAY_FILTER,},
658     {"/Analyze/Display Filter _Macros...", NULL, GTK_MENU_FUNC(macros_dialog_cb), 0, NULL, NULL,},
659     {"/Analyze/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
660     {"/Analyze/Appl_y as Filter", NULL, NULL, 0, "<Branch>", NULL,},
661     {"/Analyze/Apply as Filter/_Selected", NULL, GTK_MENU_FUNC(match_selected_ptree_cb),
662                        MATCH_SELECTED_REPLACE|MATCH_SELECTED_APPLY_NOW, NULL, NULL,},
663     {"/Analyze/Apply as Filter/_Not Selected", NULL, GTK_MENU_FUNC(match_selected_ptree_cb),
664                        MATCH_SELECTED_NOT|MATCH_SELECTED_APPLY_NOW, NULL, NULL,},
665     {"/Analyze/Apply as Filter/... _and Selected", NULL, GTK_MENU_FUNC(match_selected_ptree_cb),
666                        MATCH_SELECTED_AND|MATCH_SELECTED_APPLY_NOW, NULL, NULL,},
667     {"/Analyze/Apply as Filter/... _or Selected", NULL, GTK_MENU_FUNC(match_selected_ptree_cb),
668                        MATCH_SELECTED_OR|MATCH_SELECTED_APPLY_NOW, NULL, NULL,},
669     {"/Analyze/Apply as Filter/... a_nd not Selected", NULL, GTK_MENU_FUNC(match_selected_ptree_cb),
670                        MATCH_SELECTED_AND_NOT|MATCH_SELECTED_APPLY_NOW, NULL, NULL,},
671     {"/Analyze/Apply as Filter/... o_r not Selected", NULL, GTK_MENU_FUNC(match_selected_ptree_cb),
672                        MATCH_SELECTED_OR_NOT|MATCH_SELECTED_APPLY_NOW, NULL, NULL,},
673     {"/Analyze/_Prepare a Filter", NULL, NULL, 0, "<Branch>", NULL,},
674     {"/Analyze/Prepare a Filter/_Selected", NULL, GTK_MENU_FUNC(match_selected_ptree_cb),
675                        MATCH_SELECTED_REPLACE, NULL, NULL,},
676     {"/Analyze/Prepare a Filter/_Not Selected", NULL, GTK_MENU_FUNC(match_selected_ptree_cb),
677                        MATCH_SELECTED_NOT, NULL, NULL,},
678     {"/Analyze/Prepare a Filter/... _and Selected", NULL, GTK_MENU_FUNC(match_selected_ptree_cb),
679                        MATCH_SELECTED_AND, NULL, NULL,},
680     {"/Analyze/Prepare a Filter/... _or Selected", NULL, GTK_MENU_FUNC(match_selected_ptree_cb),
681                        MATCH_SELECTED_OR, NULL, NULL,},
682     {"/Analyze/Prepare a Filter/... a_nd not Selected", NULL, GTK_MENU_FUNC(match_selected_ptree_cb),
683                        MATCH_SELECTED_AND_NOT, NULL, NULL,},
684     {"/Analyze/Prepare a Filter/... o_r not Selected", NULL, GTK_MENU_FUNC(match_selected_ptree_cb),
685                        MATCH_SELECTED_OR_NOT, NULL, NULL,},
686     {"/Analyze/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
687     {"/Analyze/_Enabled Protocols...", "<shift><control>E", GTK_MENU_FUNC(proto_cb), 
688                        0, "<StockItem>", WIRESHARK_STOCK_CHECKBOX,},
689     {"/Analyze/Decode _As...", NULL, GTK_MENU_FUNC(decode_as_cb),
690                        0, "<StockItem>", WIRESHARK_STOCK_DECODE_AS,},
691     {"/Analyze/_User Specified Decodes...", NULL,
692                        GTK_MENU_FUNC(decode_show_cb), 0, "<StockItem>", WIRESHARK_STOCK_DECODE_AS,},
693     {"/Analyze/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
694     {"/Analyze/_Follow TCP Stream", NULL,
695                        GTK_MENU_FUNC(follow_tcp_stream_cb), 0, NULL, NULL,},
696     {"/Analyze/_Follow UDP Stream", NULL,
697                        GTK_MENU_FUNC(follow_udp_stream_cb), 0, NULL, NULL,},
698     {"/Analyze/_Follow SSL Stream", NULL,
699                        GTK_MENU_FUNC(follow_ssl_stream_cb), 0, NULL, NULL,},
700     {"/_Statistics", NULL, NULL, 0, "<Branch>", NULL,},
701     {"/Statistics/_Summary", NULL, GTK_MENU_FUNC(summary_open_cb), 0, "<StockItem>", GTK_STOCK_PROPERTIES,},
702     {"/Statistics/_Protocol Hierarchy", NULL,
703                        GTK_MENU_FUNC(proto_hier_stats_cb), 0, NULL, NULL,},
704     {"/Statistics/Conversations", NULL,
705                        GTK_MENU_FUNC(init_conversation_notebook_cb), 0, "<StockItem>", WIRESHARK_STOCK_CONVERSATIONS,},
706     {"/Statistics/Endpoints", NULL,
707                        GTK_MENU_FUNC(init_hostlist_notebook_cb), 0, "<StockItem>", WIRESHARK_STOCK_ENDPOINTS,},
708     {"/Telephon_y", NULL, NULL, 0, "<Branch>", NULL,},
709     {"/_Tools", NULL, NULL, 0, "<Branch>", NULL,},
710     {"/Tools/Firewall ACL Rules", NULL,
711                        firewall_rule_cb, 0, NULL, NULL,},
712     {"/_Help", NULL, NULL, 0, "<Branch>", NULL,},
713     {"/Help/_Contents", "F1", GTK_MENU_FUNC(topic_menu_cb), HELP_CONTENT, "<StockItem>", GTK_STOCK_HELP,},
714     {"/Help/FAQ's", NULL, GTK_MENU_FUNC(topic_menu_cb), ONLINEPAGE_FAQ, NULL, NULL,},
715     {"/Help/Manual Pages", NULL, NULL, 0, "<Branch>", NULL,},
716     {"/Help/Manual Pages/Wireshark", NULL, GTK_MENU_FUNC(topic_menu_cb), LOCALPAGE_MAN_WIRESHARK, NULL, NULL,},
717     {"/Help/Manual Pages/Wireshark Filter", NULL, GTK_MENU_FUNC(topic_menu_cb), LOCALPAGE_MAN_WIRESHARK_FILTER, NULL, NULL,},
718     {"/Help/Manual Pages/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
719     {"/Help/Manual Pages/TShark", NULL, GTK_MENU_FUNC(topic_menu_cb), LOCALPAGE_MAN_TSHARK, NULL, NULL,},
720     {"/Help/Manual Pages/RawShark", NULL, GTK_MENU_FUNC(topic_menu_cb), LOCALPAGE_MAN_RAWSHARK, NULL, NULL,},
721     {"/Help/Manual Pages/Dumpcap", NULL, GTK_MENU_FUNC(topic_menu_cb), LOCALPAGE_MAN_DUMPCAP, NULL, NULL,},
722     {"/Help/Manual Pages/Mergecap", NULL, GTK_MENU_FUNC(topic_menu_cb), LOCALPAGE_MAN_MERGECAP, NULL, NULL,},
723     {"/Help/Manual Pages/Editcap", NULL, GTK_MENU_FUNC(topic_menu_cb), LOCALPAGE_MAN_EDITCAP, NULL, NULL,},
724     {"/Help/Manual Pages/Text2pcap", NULL, GTK_MENU_FUNC(topic_menu_cb), LOCALPAGE_MAN_TEXT2PCAP, NULL, NULL,},
725     {"/Help/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
726     {"/Help/Website", NULL, GTK_MENU_FUNC(topic_menu_cb), ONLINEPAGE_HOME, "<StockItem>", GTK_STOCK_HOME,},
727     {"/Help/Wiki", NULL, GTK_MENU_FUNC(topic_menu_cb), ONLINEPAGE_WIKI, "<StockItem>", WIRESHARK_STOCK_WIKI,},
728     {"/Help/Downloads", NULL, GTK_MENU_FUNC(topic_menu_cb), ONLINEPAGE_DOWNLOAD, NULL, NULL,},
729     {"/Help/Sample Captures", NULL, GTK_MENU_FUNC(topic_menu_cb), ONLINEPAGE_SAMPLE_FILES, NULL, NULL,},
730     {"/Help/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
731     {"/Help/_Supported Protocols (slow!)", NULL, GTK_MENU_FUNC(supported_cb), 0, NULL, NULL,},
732     {"/Help/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
733     {"/Help/_About Wireshark", NULL, GTK_MENU_FUNC(about_wireshark_cb),
734                        0, "<StockItem>", WIRESHARK_STOCK_ABOUT}
735 };
736
737
738 /* calculate the number of menu_items */
739 static int nmenu_items = sizeof(menu_items) / sizeof(menu_items[0]);
740
741 /* packet list popup */
742 static GtkItemFactoryEntry packet_list_menu_items[] =
743 {
744 #ifndef NEW_PACKET_LIST
745     {"/Mark Packet (toggle)", NULL, GTK_MENU_FUNC(packet_list_mark_frame_cb), 0, NULL, NULL,},
746 #endif /* NEW_PACKET_LIST */
747     {"/Set Time Reference (toggle)", NULL, GTK_MENU_FUNC(reftime_frame_cb), REFTIME_TOGGLE, "<StockItem>", WIRESHARK_STOCK_TIME,},
748
749     {"/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
750
751     {"/Apply as Filter", NULL, NULL, 0, "<Branch>", NULL,},
752 #ifndef NEW_PACKET_LIST
753     {"/Apply as Filter/_Selected", NULL, GTK_MENU_FUNC(match_selected_plist_cb),
754                        MATCH_SELECTED_REPLACE|MATCH_SELECTED_APPLY_NOW, NULL, NULL,},
755     {"/Apply as Filter/_Not Selected", NULL, GTK_MENU_FUNC(match_selected_plist_cb),
756                        MATCH_SELECTED_NOT|MATCH_SELECTED_APPLY_NOW, NULL, NULL,},
757     {"/Apply as Filter/... _and Selected", NULL, GTK_MENU_FUNC(match_selected_plist_cb),
758                        MATCH_SELECTED_AND|MATCH_SELECTED_APPLY_NOW, NULL, NULL,},
759     {"/Apply as Filter/... _or Selected", NULL, GTK_MENU_FUNC(match_selected_plist_cb),
760                        MATCH_SELECTED_OR|MATCH_SELECTED_APPLY_NOW, NULL, NULL,},
761     {"/Apply as Filter/... a_nd not Selected", NULL, GTK_MENU_FUNC(match_selected_plist_cb),
762                        MATCH_SELECTED_AND_NOT|MATCH_SELECTED_APPLY_NOW, NULL, NULL,},
763     {"/Apply as Filter/... o_r not Selected", NULL, GTK_MENU_FUNC(match_selected_plist_cb),
764                        MATCH_SELECTED_OR_NOT|MATCH_SELECTED_APPLY_NOW, NULL, NULL,},
765     {"/Prepare a Filter", NULL, NULL, 0, "<Branch>", NULL,},
766     {"/Prepare a Filter/_Selected", NULL, GTK_MENU_FUNC(match_selected_plist_cb),
767                        MATCH_SELECTED_REPLACE, NULL, NULL,},
768     {"/Prepare a Filter/_Not Selected", NULL, GTK_MENU_FUNC(match_selected_plist_cb),
769                        MATCH_SELECTED_NOT, NULL, NULL,},
770     {"/Prepare a Filter/... _and Selected", NULL, GTK_MENU_FUNC(match_selected_plist_cb),
771                        MATCH_SELECTED_AND, NULL, NULL,},
772     {"/Prepare a Filter/... _or Selected", NULL, GTK_MENU_FUNC(match_selected_plist_cb),
773                        MATCH_SELECTED_OR, NULL, NULL,},
774     {"/Prepare a Filter/... a_nd not Selected", NULL, GTK_MENU_FUNC(match_selected_plist_cb),
775                        MATCH_SELECTED_AND_NOT, NULL, NULL,},
776     {"/Prepare a Filter/... o_r not Selected", NULL, GTK_MENU_FUNC(match_selected_plist_cb),
777                        MATCH_SELECTED_OR_NOT, NULL, NULL,},
778 #endif /* NEW_PACKET_LIST */
779     {"/Conversation Filter", NULL, NULL, 0, "<Branch>",NULL,},
780     {"/Conversation Filter/Ethernet", NULL, GTK_MENU_FUNC(conversation_cb),
781                        CONV_ETHER, NULL, NULL,},
782     {"/Conversation Filter/IP", NULL, GTK_MENU_FUNC(conversation_cb),
783                        CONV_IP, NULL, NULL,},
784     {"/Conversation Filter/TCP", NULL, GTK_MENU_FUNC(conversation_cb),
785                        CONV_TCP, NULL, NULL,},
786     {"/Conversation Filter/UDP", NULL, GTK_MENU_FUNC(conversation_cb),
787                        CONV_UDP, NULL, NULL,},
788     {"/Conversation Filter/PN-CBA Server", NULL, GTK_MENU_FUNC(conversation_cb),
789                        CONV_CBA, NULL, NULL,},
790
791     {"/Colorize Conversation", NULL, NULL, 0, "<Branch>",NULL,},
792     {"/Colorize Conversation/Ethernet", NULL, NULL, 0, "<Branch>",NULL,},
793     {"/Colorize Conversation/Ethernet/Color 1", NULL,
794                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_ETHER+1*256, "<StockItem>", WIRESHARK_STOCK_COLOR1,},
795     {"/Colorize Conversation/Ethernet/Color 2", NULL,
796                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_ETHER+2*256, "<StockItem>", WIRESHARK_STOCK_COLOR2,},
797     {"/Colorize Conversation/Ethernet/Color 3", NULL,
798                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_ETHER+3*256, "<StockItem>", WIRESHARK_STOCK_COLOR3,},
799     {"/Colorize Conversation/Ethernet/Color 4", NULL,
800                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_ETHER+4*256, "<StockItem>", WIRESHARK_STOCK_COLOR4,},
801     {"/Colorize Conversation/Ethernet/Color 5", NULL,
802                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_ETHER+5*256, "<StockItem>", WIRESHARK_STOCK_COLOR5,},
803     {"/Colorize Conversation/Ethernet/Color 6", NULL,
804                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_ETHER+6*256, "<StockItem>", WIRESHARK_STOCK_COLOR6,},
805     {"/Colorize Conversation/Ethernet/Color 7", NULL,
806                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_ETHER+7*256, "<StockItem>", WIRESHARK_STOCK_COLOR7,},
807     {"/Colorize Conversation/Ethernet/Color 8", NULL,
808                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_ETHER+8*256, "<StockItem>", WIRESHARK_STOCK_COLOR8,},
809     {"/Colorize Conversation/Ethernet/Color 9", NULL,
810                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_ETHER+9*256, "<StockItem>", WIRESHARK_STOCK_COLOR9,},
811     {"/Colorize Conversation/Ethernet/Color 10", NULL,
812                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_ETHER+10*256, "<StockItem>", WIRESHARK_STOCK_COLOR0,},
813     {"/Colorize Conversation/Ethernet/<separator>", NULL,
814                        NULL, 0, "<Separator>",NULL,},
815     {"/Colorize Conversation/Ethernet/New Coloring Rule...", NULL,
816                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_ETHER, "<StockItem>", GTK_STOCK_SELECT_COLOR,},
817     {"/Colorize Conversation/IP", NULL, NULL, 0, "<Branch>",NULL,},
818     {"/Colorize Conversation/IP/Color 1", NULL,
819                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_IP+1*256, "<StockItem>", WIRESHARK_STOCK_COLOR1,},
820     {"/Colorize Conversation/IP/Color 2", NULL,
821                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_IP+2*256, "<StockItem>", WIRESHARK_STOCK_COLOR2,},
822     {"/Colorize Conversation/IP/Color 3", NULL,
823                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_IP+3*256, "<StockItem>", WIRESHARK_STOCK_COLOR3,},
824     {"/Colorize Conversation/IP/Color 4", NULL,
825                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_IP+4*256, "<StockItem>", WIRESHARK_STOCK_COLOR4,},
826     {"/Colorize Conversation/IP/Color 5", NULL,
827                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_IP+5*256, "<StockItem>", WIRESHARK_STOCK_COLOR5,},
828     {"/Colorize Conversation/IP/Color 6", NULL,
829                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_IP+6*256, "<StockItem>", WIRESHARK_STOCK_COLOR6,},
830     {"/Colorize Conversation/IP/Color 7", NULL,
831                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_IP+7*256, "<StockItem>", WIRESHARK_STOCK_COLOR7,},
832     {"/Colorize Conversation/IP/Color 8", NULL,
833                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_IP+8*256, "<StockItem>", WIRESHARK_STOCK_COLOR8,},
834     {"/Colorize Conversation/IP/Color 9", NULL,
835                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_IP+9*256, "<StockItem>", WIRESHARK_STOCK_COLOR9,},
836     {"/Colorize Conversation/IP/Color 10", NULL,
837                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_IP+10*256, "<StockItem>", WIRESHARK_STOCK_COLOR0,},
838     {"/Colorize Conversation/IP/<separator>", NULL,
839                        NULL, 0, "<Separator>",NULL,},
840     {"/Colorize Conversation/IP/New Coloring Rule...", NULL,
841                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_IP, "<StockItem>", GTK_STOCK_SELECT_COLOR,},
842     {"/Colorize Conversation/TCP", NULL, NULL, 0, "<Branch>",NULL,},
843     {"/Colorize Conversation/TCP/Color 1", NULL,
844                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_TCP+1*256, "<StockItem>", WIRESHARK_STOCK_COLOR1,},
845     {"/Colorize Conversation/TCP/Color 2", NULL,
846                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_TCP+2*256, "<StockItem>", WIRESHARK_STOCK_COLOR2,},
847     {"/Colorize Conversation/TCP/Color 3", NULL,
848                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_TCP+3*256, "<StockItem>", WIRESHARK_STOCK_COLOR3,},
849     {"/Colorize Conversation/TCP/Color 4", NULL,
850                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_TCP+4*256, "<StockItem>", WIRESHARK_STOCK_COLOR4,},
851     {"/Colorize Conversation/TCP/Color 5", NULL,
852                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_TCP+5*256, "<StockItem>", WIRESHARK_STOCK_COLOR5,},
853     {"/Colorize Conversation/TCP/Color 6", NULL,
854                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_TCP+6*256, "<StockItem>", WIRESHARK_STOCK_COLOR6,},
855     {"/Colorize Conversation/TCP/Color 7", NULL,
856                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_TCP+7*256, "<StockItem>", WIRESHARK_STOCK_COLOR7,},
857     {"/Colorize Conversation/TCP/Color 8", NULL,
858                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_TCP+8*256, "<StockItem>", WIRESHARK_STOCK_COLOR8,},
859     {"/Colorize Conversation/TCP/Color 9", NULL,
860                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_TCP+9*256, "<StockItem>", WIRESHARK_STOCK_COLOR9,},
861     {"/Colorize Conversation/TCP/Color 10", NULL,
862                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_TCP+10*256, "<StockItem>", WIRESHARK_STOCK_COLOR0,},
863     {"/Colorize Conversation/TCP/<separator>", NULL,
864                        NULL, 0, "<Separator>",NULL,},
865     {"/Colorize Conversation/TCP/New Coloring Rule...", NULL,
866                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_TCP, "<StockItem>", GTK_STOCK_SELECT_COLOR,},
867     {"/Colorize Conversation/UDP", NULL, NULL, 0, "<Branch>",NULL,},
868     {"/Colorize Conversation/UDP/Color 1", NULL,
869                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_UDP+1*256, "<StockItem>", WIRESHARK_STOCK_COLOR1,},
870     {"/Colorize Conversation/UDP/Color 2", NULL,
871                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_UDP+2*256, "<StockItem>", WIRESHARK_STOCK_COLOR2,},
872     {"/Colorize Conversation/UDP/Color 3", NULL,
873                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_UDP+3*256, "<StockItem>", WIRESHARK_STOCK_COLOR3,},
874     {"/Colorize Conversation/UDP/Color 4", NULL,
875                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_UDP+4*256, "<StockItem>", WIRESHARK_STOCK_COLOR4,},
876     {"/Colorize Conversation/UDP/Color 5", NULL,
877                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_UDP+5*256, "<StockItem>", WIRESHARK_STOCK_COLOR5,},
878     {"/Colorize Conversation/UDP/Color 6", NULL,
879                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_UDP+6*256, "<StockItem>", WIRESHARK_STOCK_COLOR6,},
880     {"/Colorize Conversation/UDP/Color 7", NULL,
881                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_UDP+7*256, "<StockItem>", WIRESHARK_STOCK_COLOR7,},
882     {"/Colorize Conversation/UDP/Color 8", NULL,
883                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_UDP+8*256, "<StockItem>", WIRESHARK_STOCK_COLOR8,},
884     {"/Colorize Conversation/UDP/Color 9", NULL,
885                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_UDP+9*256, "<StockItem>", WIRESHARK_STOCK_COLOR9,},
886     {"/Colorize Conversation/UDP/Color 10", NULL,
887                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_UDP+10*256, "<StockItem>", WIRESHARK_STOCK_COLOR0,},
888     {"/Colorize Conversation/UDP/<separator>", NULL,
889                        NULL, 0, "<Separator>",NULL,},
890     {"/Colorize Conversation/UDP/New Coloring Rule...", NULL,
891                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_UDP, "<StockItem>", GTK_STOCK_SELECT_COLOR,},
892     {"/Colorize Conversation/PN-CBA Server", NULL, NULL, 0, "<Branch>",NULL,},
893     {"/Colorize Conversation/PN-CBA Server/Color 1", NULL,
894                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_CBA+1*256, "<StockItem>", WIRESHARK_STOCK_COLOR1,},
895     {"/Colorize Conversation/PN-CBA Server/Color 2", NULL,
896                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_CBA+2*256, "<StockItem>", WIRESHARK_STOCK_COLOR2,},
897     {"/Colorize Conversation/PN-CBA Server/Color 3", NULL,
898                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_CBA+3*256, "<StockItem>", WIRESHARK_STOCK_COLOR3,},
899     {"/Colorize Conversation/PN-CBA Server/Color 4", NULL,
900                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_CBA+4*256, "<StockItem>", WIRESHARK_STOCK_COLOR4,},
901     {"/Colorize Conversation/PN-CBA Server/Color 5", NULL,
902                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_CBA+5*256, "<StockItem>", WIRESHARK_STOCK_COLOR5,},
903     {"/Colorize Conversation/PN-CBA Server/Color 6", NULL,
904                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_CBA+6*256, "<StockItem>", WIRESHARK_STOCK_COLOR6,},
905     {"/Colorize Conversation/PN-CBA Server/Color 7", NULL,
906                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_CBA+7*256, "<StockItem>", WIRESHARK_STOCK_COLOR7,},
907     {"/Colorize Conversation/PN-CBA Server/Color 8", NULL,
908                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_CBA+8*256, "<StockItem>", WIRESHARK_STOCK_COLOR8,},
909     {"/Colorize Conversation/PN-CBA Server/Color 9", NULL,
910                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_CBA+9*256, "<StockItem>", WIRESHARK_STOCK_COLOR9,},
911     {"/Colorize Conversation/PN-CBA Server/Color 10", NULL,
912                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_CBA+10*256, "<StockItem>", WIRESHARK_STOCK_COLOR0,},
913     {"/Colorize Conversation/PN-CBA Server/<separator>", NULL,
914                        NULL, 0, "<Separator>",NULL,},
915     {"/Colorize Conversation/PN-CBA Server/New Coloring Rule...", NULL,
916                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_CBA, "<StockItem>", GTK_STOCK_SELECT_COLOR,},
917
918     {"/SCTP", NULL, NULL, 0, "<Branch>",NULL,},
919     {"/SCTP/Analyse this Association", NULL, GTK_MENU_FUNC(sctp_analyse_start),
920                        0, NULL,NULL,},
921     {"/SCTP/Prepare Filter for this Association", NULL, (sctp_set_assoc_filter),
922                        0, NULL,NULL,},
923
924     {"/Follow TCP Stream", NULL, (follow_tcp_stream_cb),
925                        0, NULL, NULL,},
926     {"/Follow UDP Stream", NULL, (follow_udp_stream_cb),
927                        0, NULL, NULL,},
928     {"/Follow SSL Stream", NULL, (follow_ssl_stream_cb),
929                        0, NULL, NULL,},
930
931     {"/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
932 #ifndef NEW_PACKET_LIST
933     {"/Copy", NULL, NULL, 0, "<Branch>", NULL,},
934     {"/Copy/Summary (Text)", NULL, GTK_MENU_FUNC(packet_list_copy_summary_cb), CS_TEXT, NULL, NULL,},
935     {"/Copy/Summary (CSV)", NULL, GTK_MENU_FUNC(packet_list_copy_summary_cb), CS_CSV, NULL, NULL,},
936     {"/Copy/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
937     {"/Copy/As Filter", NULL, GTK_MENU_FUNC(match_selected_plist_cb),
938                        MATCH_SELECTED_REPLACE|MATCH_SELECTED_COPY_ONLY, NULL, NULL,},
939 #endif /* NEW_PACKET_LIST */
940     {"/Copy/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
941     {"/Copy/Bytes (Offset Hex Text)", NULL, GTK_MENU_FUNC(copy_hex_cb), CD_ALLINFO, NULL, NULL,},
942     {"/Copy/Bytes (Offset Hex)", NULL, GTK_MENU_FUNC(copy_hex_cb), CD_HEXCOLUMNS, NULL, NULL,},
943     {"/Copy/Bytes (Printable Text Only)", NULL, GTK_MENU_FUNC(copy_hex_cb), CD_TEXTONLY, NULL, NULL,},
944     {"/Copy/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
945     {"/Copy/Bytes (Hex Stream)", NULL, GTK_MENU_FUNC(copy_hex_cb), CD_HEX, NULL, NULL,},
946     {"/Copy/Bytes (Binary Stream)", NULL, GTK_MENU_FUNC(copy_hex_cb), CD_BINARY, NULL, NULL,},
947
948     {"/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
949
950     {"/Decode As...", NULL, GTK_MENU_FUNC(decode_as_cb), 0, "<StockItem>", WIRESHARK_STOCK_DECODE_AS,},
951     {"/Print...", NULL, GTK_MENU_FUNC(file_print_selected_cmd_cb), 0, "<StockItem>", GTK_STOCK_PRINT,},
952     {"/Show Packet in New Window", NULL, GTK_MENU_FUNC(new_window_cb),
953                        0, NULL, NULL}
954 };
955
956 static GtkItemFactoryEntry tree_view_menu_items[] =
957 {
958
959     {"/Expand Subtrees", NULL, GTK_MENU_FUNC(expand_tree_cb), 0, NULL, NULL,},
960     {"/Expand All", NULL, GTK_MENU_FUNC(expand_all_cb), 0, NULL, NULL,},
961     {"/Collapse All", NULL, GTK_MENU_FUNC(collapse_all_cb), 0, NULL, NULL,},
962
963     {"/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
964
965     {"/Apply as Filter", NULL, NULL, 0, "<Branch>", NULL,},
966     {"/Apply as Filter/_Selected", NULL, GTK_MENU_FUNC(match_selected_ptree_cb),
967                        MATCH_SELECTED_REPLACE|MATCH_SELECTED_APPLY_NOW, NULL, NULL,},
968     {"/Apply as Filter/_Not Selected", NULL, GTK_MENU_FUNC(match_selected_ptree_cb),
969                        MATCH_SELECTED_NOT|MATCH_SELECTED_APPLY_NOW, NULL, NULL,},
970     {"/Apply as Filter/... _and Selected", NULL, GTK_MENU_FUNC(match_selected_ptree_cb),
971                        MATCH_SELECTED_AND|MATCH_SELECTED_APPLY_NOW, NULL, NULL,},
972     {"/Apply as Filter/... _or Selected", NULL, GTK_MENU_FUNC(match_selected_ptree_cb),
973                        MATCH_SELECTED_OR|MATCH_SELECTED_APPLY_NOW, NULL, NULL,},
974     {"/Apply as Filter/... a_nd not Selected", NULL, GTK_MENU_FUNC(match_selected_ptree_cb),
975                        MATCH_SELECTED_AND_NOT|MATCH_SELECTED_APPLY_NOW, NULL, NULL,},
976     {"/Apply as Filter/... o_r not Selected", NULL, GTK_MENU_FUNC(match_selected_ptree_cb),
977                        MATCH_SELECTED_OR_NOT|MATCH_SELECTED_APPLY_NOW, NULL, NULL,},
978
979     {"/Prepare a Filter", NULL, NULL, 0, "<Branch>", NULL,},
980     {"/Prepare a Filter/_Selected", NULL, GTK_MENU_FUNC(match_selected_ptree_cb),
981                        MATCH_SELECTED_REPLACE, NULL, NULL,},
982     {"/Prepare a Filter/_Not Selected", NULL, GTK_MENU_FUNC(match_selected_ptree_cb),
983                        MATCH_SELECTED_NOT, NULL, NULL,},
984     {"/Prepare a Filter/... _and Selected", NULL, GTK_MENU_FUNC(match_selected_ptree_cb),
985                        MATCH_SELECTED_AND, NULL, NULL,},
986     {"/Prepare a Filter/... _or Selected", NULL, GTK_MENU_FUNC(match_selected_ptree_cb),
987                        MATCH_SELECTED_OR, NULL, NULL,},
988     {"/Prepare a Filter/... a_nd not Selected", NULL, GTK_MENU_FUNC(match_selected_ptree_cb),
989                        MATCH_SELECTED_AND_NOT, NULL, NULL,},
990     {"/Prepare a Filter/... o_r not Selected", NULL, GTK_MENU_FUNC(match_selected_ptree_cb),
991                        MATCH_SELECTED_OR_NOT, NULL, NULL,},
992
993     {"/Colorize with Filter", NULL, NULL, 0, "<Branch>", NULL,},
994     {"/Colorize with Filter/Color 1", NULL, GTK_MENU_FUNC(colorize_selected_ptree_cb), 1, "<StockItem>", WIRESHARK_STOCK_COLOR1,},
995     {"/Colorize with Filter/Color 2", NULL, GTK_MENU_FUNC(colorize_selected_ptree_cb), 2, "<StockItem>", WIRESHARK_STOCK_COLOR2,},
996     {"/Colorize with Filter/Color 3", NULL, GTK_MENU_FUNC(colorize_selected_ptree_cb), 3, "<StockItem>", WIRESHARK_STOCK_COLOR3,},
997     {"/Colorize with Filter/Color 4", NULL, GTK_MENU_FUNC(colorize_selected_ptree_cb), 4, "<StockItem>", WIRESHARK_STOCK_COLOR4,},
998     {"/Colorize with Filter/Color 5", NULL, GTK_MENU_FUNC(colorize_selected_ptree_cb), 5, "<StockItem>", WIRESHARK_STOCK_COLOR5,},
999     {"/Colorize with Filter/Color 6", NULL, GTK_MENU_FUNC(colorize_selected_ptree_cb), 6, "<StockItem>", WIRESHARK_STOCK_COLOR6,},
1000     {"/Colorize with Filter/Color 7", NULL, GTK_MENU_FUNC(colorize_selected_ptree_cb), 7, "<StockItem>", WIRESHARK_STOCK_COLOR7,},
1001     {"/Colorize with Filter/Color 8", NULL, GTK_MENU_FUNC(colorize_selected_ptree_cb), 8, "<StockItem>", WIRESHARK_STOCK_COLOR8,},
1002     {"/Colorize with Filter/Color 9", NULL, GTK_MENU_FUNC(colorize_selected_ptree_cb), 9, "<StockItem>", WIRESHARK_STOCK_COLOR9,},
1003     {"/Colorize with Filter/Color 10", NULL, GTK_MENU_FUNC(colorize_selected_ptree_cb), 10, "<StockItem>", WIRESHARK_STOCK_COLOR0,},
1004     {"/Colorize with Filter/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
1005     {"/Colorize with Filter/New Coloring Rule...", NULL, GTK_MENU_FUNC(colorize_selected_ptree_cb), 0, "<StockItem>", GTK_STOCK_SELECT_COLOR,},
1006
1007     {"/Follow TCP Stream", NULL, GTK_MENU_FUNC(follow_tcp_stream_cb),
1008                        0, NULL, NULL,},
1009     {"/Follow UDP Stream", NULL, GTK_MENU_FUNC(follow_udp_stream_cb),
1010                        0, NULL, NULL,},
1011     {"/Follow SSL Stream", NULL, GTK_MENU_FUNC(follow_ssl_stream_cb),
1012                        0, NULL, NULL,},
1013
1014     {"/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
1015
1016     {"/Copy", NULL, NULL, 0, "<Branch>", NULL,},
1017     {"/Copy/Description", NULL, GTK_MENU_FUNC(copy_selected_plist_cb), COPY_SELECTED_DESCRIPTION, NULL, NULL,},
1018     {"/Copy/Fieldname", NULL, GTK_MENU_FUNC(copy_selected_plist_cb), COPY_SELECTED_FIELDNAME, NULL, NULL,},
1019     {"/Copy/Value", NULL, GTK_MENU_FUNC(copy_selected_plist_cb), COPY_SELECTED_VALUE, NULL, NULL,},
1020     {"/Copy/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
1021     {"/Copy/As Filter", NULL, GTK_MENU_FUNC(match_selected_ptree_cb), MATCH_SELECTED_REPLACE|MATCH_SELECTED_COPY_ONLY, NULL, NULL,},
1022     {"/Copy/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
1023     {"/Copy/Bytes (Offset Hex Text)", NULL, GTK_MENU_FUNC(copy_hex_cb), CD_ALLINFO | CD_FLAGS_SELECTEDONLY, NULL, NULL,},
1024     {"/Copy/Bytes (Offset Hex)", NULL, GTK_MENU_FUNC(copy_hex_cb), CD_HEXCOLUMNS | CD_FLAGS_SELECTEDONLY, NULL, NULL,},
1025     {"/Copy/Bytes (Printable Text Only)", NULL, GTK_MENU_FUNC(copy_hex_cb), CD_TEXTONLY | CD_FLAGS_SELECTEDONLY, NULL, NULL,},
1026     {"/Copy/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
1027     {"/Copy/Bytes (Hex Stream)", NULL, GTK_MENU_FUNC(copy_hex_cb), CD_HEX | CD_FLAGS_SELECTEDONLY, NULL, NULL,},
1028     {"/Copy/Bytes (Binary Stream)", NULL, GTK_MENU_FUNC(copy_hex_cb), CD_BINARY | CD_FLAGS_SELECTEDONLY, NULL, NULL,},
1029
1030     {"/Export Selected Packet Bytes...", NULL, GTK_MENU_FUNC(savehex_cb),
1031                        0, NULL, NULL,},
1032
1033     {"/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
1034
1035     {"/Wiki Protocol Page", NULL, GTK_MENU_FUNC(selected_ptree_info_cb),
1036                        0, "<StockItem>", WIRESHARK_STOCK_WIKI,},
1037     {"/Filter Field Reference", NULL, GTK_MENU_FUNC(selected_ptree_ref_cb),
1038                        0, "<StockItem>", WIRESHARK_STOCK_INTERNET,},
1039     {"/Protocol Preferences", NULL, NULL, 0, NULL, NULL,},
1040     {"/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
1041     {"/Decode As...", NULL, GTK_MENU_FUNC(decode_as_cb), 0, "<StockItem>", WIRESHARK_STOCK_DECODE_AS,},
1042     {"/Disable Protocol...", NULL, GTK_MENU_FUNC(proto_disable_cb), 0, "<StockItem>", WIRESHARK_STOCK_CHECKBOX,},
1043     {"/_Resolve Name", NULL, GTK_MENU_FUNC(resolve_name_cb), 0, NULL, NULL,},
1044     {"/_Go to Corresponding Packet", NULL, GTK_MENU_FUNC(goto_framenum_cb), 0, NULL, NULL,}
1045 };
1046
1047
1048 static int initialize = TRUE;
1049 static GtkItemFactory *main_menu_factory = NULL;
1050 static GtkItemFactory *packet_list_menu_factory = NULL;
1051 static GtkItemFactory *tree_view_menu_factory = NULL;
1052 static GtkItemFactory *hexdump_menu_factory = NULL;
1053
1054 static GSList *popup_menu_list = NULL;
1055
1056 static GtkAccelGroup *grp;
1057
1058 GtkWidget *
1059 main_menu_new(GtkAccelGroup ** table) {
1060     GtkWidget *menubar;
1061 #ifdef HAVE_IGE_MAC_INTEGRATION
1062     GtkWidget *quit_item, *about_item, *preferences_item;
1063     IgeMacMenuGroup *group;
1064 #endif
1065
1066     grp = gtk_accel_group_new();
1067
1068     if (initialize)
1069         menus_init();
1070
1071     menubar = main_menu_factory->widget;
1072
1073 #ifdef HAVE_IGE_MAC_INTEGRATION
1074     if(prefs.gui_macosx_style) {
1075         ige_mac_menu_set_menu_bar(GTK_MENU_SHELL(menubar));
1076         ige_mac_menu_set_global_key_handler_enabled(TRUE);
1077
1078         /* Create menu items to populate the application menu with.  We have to
1079          * do this because we are still using the old GtkItemFactory API for
1080          * the main menu. */
1081         group = ige_mac_menu_add_app_menu_group();
1082         about_item = gtk_menu_item_new_with_label("About");
1083         g_signal_connect(about_item, "activate", G_CALLBACK(about_wireshark_cb),
1084                          NULL);
1085         ige_mac_menu_add_app_menu_item(group, GTK_MENU_ITEM(about_item), NULL);
1086
1087         group = ige_mac_menu_add_app_menu_group();
1088         preferences_item = gtk_menu_item_new_with_label("Preferences");
1089         g_signal_connect(preferences_item, "activate", G_CALLBACK(prefs_cb),
1090                          NULL);
1091         ige_mac_menu_add_app_menu_item(group, GTK_MENU_ITEM(preferences_item),
1092                                        NULL);
1093     }
1094
1095     /* The quit item in the application menu shows up whenever ige mac
1096      * integration is enabled, even if the OS X UI style in Wireshark isn't
1097      * turned on. */
1098     quit_item = gtk_menu_item_new_with_label("Quit");
1099     g_signal_connect(quit_item, "activate", G_CALLBACK(file_quit_cmd_cb), NULL);
1100     ige_mac_menu_set_quit_menu_item(GTK_MENU_ITEM(quit_item));
1101 #endif
1102
1103     if (table)
1104         *table = grp;
1105
1106     return menubar;
1107 }
1108
1109
1110 void menu_dissector_filter_cb(  GtkWidget *widget _U_,
1111                                 gpointer callback_data,
1112                                 guint callback_action _U_)
1113 {
1114     dissector_filter_t      *filter_entry = callback_data;
1115     GtkWidget               *filter_te;
1116     const char              *buf;    
1117
1118
1119     filter_te = g_object_get_data(G_OBJECT(popup_menu_object), E_DFILTER_TE_KEY);
1120
1121     /* XXX - this gets the packet_info of the last dissected packet, */
1122     /* which is not necessarily the last selected packet */
1123     /* e.g. "Update list of packets in real time" won't work correct */
1124     buf = filter_entry->build_filter_string(&cfile.edt->pi);
1125
1126     gtk_entry_set_text(GTK_ENTRY(filter_te), buf);
1127
1128     /* Run the display filter so it goes in effect - even if it's the
1129        same as the previous display filter. */
1130     main_filter_packets(&cfile, buf, TRUE);
1131
1132     g_free( (void *) buf);
1133 }
1134
1135 gboolean menu_dissector_filter_spe_cb(frame_data *fd _U_, epan_dissect_t *edt, gpointer callback_data) {
1136     dissector_filter_t *filter_entry = callback_data;
1137
1138     /* XXX - this gets the packet_info of the last dissected packet, */
1139     /* which is not necessarily the last selected packet */
1140     /* e.g. "Update list of packets in real time" won't work correct */
1141     return (edt != NULL) ? filter_entry->is_filter_valid(&edt->pi) : FALSE;
1142 }
1143
1144 void menu_dissector_filter(void) {
1145     GList *list_entry = dissector_filter_list;
1146     dissector_filter_t *filter_entry;
1147
1148     while(list_entry != NULL) {
1149         filter_entry = list_entry->data;
1150
1151         register_stat_menu_item(filter_entry->name, REGISTER_ANALYZE_GROUP_CONVERSATION_FILTER,
1152             menu_dissector_filter_cb,
1153             menu_dissector_filter_spe_cb,
1154             NULL /* selected_tree_row_enabled */,
1155             filter_entry);
1156
1157         list_entry = g_list_next(list_entry);
1158     }
1159 }
1160
1161
1162 static void
1163 menus_init(void) {
1164     if (initialize) {
1165         initialize = FALSE;
1166
1167     /* packet list pop-up menu */
1168     packet_list_menu_factory = gtk_item_factory_new(GTK_TYPE_MENU, "<main>", NULL);
1169     popup_menu_object = gtk_menu_new();
1170     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);
1171     g_object_set_data(G_OBJECT(popup_menu_object), PM_PACKET_LIST_KEY,
1172                     packet_list_menu_factory->widget);
1173     popup_menu_list = g_slist_append((GSList *)popup_menu_list, packet_list_menu_factory);
1174
1175     /* packet detail pop-up menu */
1176     tree_view_menu_factory = gtk_item_factory_new(GTK_TYPE_MENU, "<main>", NULL);
1177     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);
1178     g_object_set_data(G_OBJECT(popup_menu_object), PM_TREE_VIEW_KEY,
1179                     tree_view_menu_factory->widget);
1180     popup_menu_list = g_slist_append((GSList *)popup_menu_list, tree_view_menu_factory);
1181
1182     /*
1183      * Hex dump pop-up menu.
1184      * We provide our own empty menu to suppress the default pop-up menu
1185      * for text widgets.
1186      */
1187     hexdump_menu_factory = gtk_item_factory_new(GTK_TYPE_MENU, "<main>", NULL);
1188     g_object_set_data(G_OBJECT(popup_menu_object), PM_HEXDUMP_KEY,
1189                     hexdump_menu_factory->widget);
1190     popup_menu_list = g_slist_append((GSList *)popup_menu_list, hexdump_menu_factory);
1191
1192     /* main */
1193     main_menu_factory = gtk_item_factory_new(GTK_TYPE_MENU_BAR, "<main>", grp);
1194     gtk_item_factory_create_items_ac(main_menu_factory, nmenu_items, menu_items, NULL, 2);
1195
1196     menu_dissector_filter();
1197     merge_all_tap_menus(tap_menu_tree_root);
1198
1199     /* Initialize enabled/disabled state of menu items */
1200     set_menus_for_capture_file(NULL);
1201 #if 0
1202     /* Un-#if this when we actually implement Cut/Copy/Paste.
1203        Then make sure you enable them when they can be done. */
1204     set_menu_sensitivity(main_menu_factory, "/Edit/Cut", FALSE);
1205     set_menu_sensitivity(main_menu_factory, "/Edit/Copy", FALSE);
1206     set_menu_sensitivity(main_menu_factory, "/Edit/Paste", FALSE);
1207 #endif
1208
1209     set_menus_for_captured_packets(FALSE);
1210     set_menus_for_selected_packet(&cfile);
1211     set_menus_for_selected_tree_row(&cfile);
1212     set_menus_for_capture_in_progress(FALSE);
1213     set_menus_for_file_set(/* dialog */TRUE, /* previous file */ FALSE, /* next_file */ FALSE);
1214
1215     /* init with an empty recent files list */
1216     clear_menu_recent_capture_file_cmd_cb(NULL, NULL);
1217
1218     }
1219 }
1220
1221
1222 static gint tap_menu_item_add_compare(gconstpointer a, gconstpointer b)
1223 {
1224     return strcmp(
1225         ((const menu_item_t *) a)->name,
1226         ((const menu_item_t *) b)->name);
1227 }
1228
1229
1230 /* add a menuitem below the current node */
1231 static GList * tap_menu_item_add(
1232     char *name,
1233     gint group,
1234     const char *stock_id,
1235     GtkItemFactoryCallback callback,
1236     gboolean (*selected_packet_enabled)(frame_data *, epan_dissect_t *, gpointer callback_data),
1237     gboolean (*selected_tree_row_enabled)(field_info *, gpointer callback_data),
1238     gpointer callback_data,
1239     GList *curnode)
1240 {
1241     menu_item_t *curr;
1242     menu_item_t *child;
1243
1244
1245     child = g_malloc(sizeof (menu_item_t));
1246     child->name             = name;
1247     child->group            = group;
1248     child->stock_id         = stock_id;
1249     child->callback         = callback;
1250     child->selected_packet_enabled = selected_packet_enabled;
1251     child->selected_tree_row_enabled = selected_tree_row_enabled;
1252     child->callback_data    = callback_data;
1253     child->enabled          = FALSE;
1254     child->children         = NULL;
1255
1256     /* insert the new child node into the parent */
1257     curr = curnode->data;
1258     curr->children = g_list_insert_sorted(curr->children, child, tap_menu_item_add_compare);
1259
1260     /* return the new node */
1261     /* XXX: improve this */
1262     return g_list_find(curr->children, child);
1263 }
1264
1265 /*
1266  * Add a new menu item for a tap.
1267  * This must be called after we've created the main menu, so it can't
1268  * be called from the routine that registers taps - we have to introduce
1269  * another per-tap registration routine.
1270  *
1271  * "callback" gets called when the menu item is selected; it should do
1272  * the work of creating the tap window.
1273  *
1274  * "selected_packet_enabled" gets called by "set_menus_for_selected_packet()";
1275  * it's passed a Boolean that's TRUE if a packet is selected and FALSE
1276  * otherwise, and should return TRUE if the tap will work now (which
1277  * might depend on whether a packet is selected and, if one is, on the
1278  * packet) and FALSE if not.
1279  *
1280  * "selected_tree_row_enabled" gets called by
1281  * "set_menus_for_selected_tree_row()"; it's passed a Boolean that's TRUE if
1282  * a protocol tree row is selected and FALSE otherwise, and should return
1283  * TRUE if the tap will work now (which might depend on whether a tree row
1284  * is selected and, if one is, on the tree row) and FALSE if not.
1285  */
1286 void
1287 register_stat_menu_item_stock(
1288     const char *name,
1289     register_stat_group_t group,
1290     const char *stock_id,
1291     GtkItemFactoryCallback callback,
1292     gboolean (*selected_packet_enabled)(frame_data *, epan_dissect_t *, gpointer callback_data),
1293     gboolean (*selected_tree_row_enabled)(field_info *, gpointer callback_data),
1294     gpointer callback_data)
1295 {
1296     /*static const char toolspath[] = "/Statistics/";*/
1297     const char *toolspath;
1298     const char *p;
1299     char *menupath;
1300     size_t menupathlen;
1301     menu_item_t *child;
1302     GList *curnode;
1303     GList *childnode;
1304
1305     /*
1306      * The menu path must be relative.
1307      */
1308     g_assert(*name != '/');
1309
1310     switch(group) {
1311     case(REGISTER_STAT_GROUP_GENERIC): toolspath = "/Statistics/"; break;
1312     case(REGISTER_STAT_GROUP_CONVERSATION_LIST): toolspath = "/Statistics/_Conversation List/"; break;
1313     case(REGISTER_STAT_GROUP_ENDPOINT_LIST): toolspath = "/Statistics/_Endpoint List/"; break;
1314     case(REGISTER_STAT_GROUP_RESPONSE_TIME): toolspath = "/Statistics/Service _Response Time/"; break;
1315     case(REGISTER_STAT_GROUP_UNSORTED): toolspath = "/Statistics/"; break;
1316     case(REGISTER_ANALYZE_GROUP_UNSORTED): toolspath = "/Analyze/"; break;
1317     case(REGISTER_ANALYZE_GROUP_CONVERSATION_FILTER): toolspath = "/Analyze/Conversation Filter/"; break;
1318     case(REGISTER_STAT_GROUP_TELEPHONY): toolspath = "/Telephony/"; break;
1319     case(REGISTER_TOOLS_GROUP_UNSORTED): toolspath = "/Tools/"; break;
1320     default:
1321         g_assert(!"no such menu group");
1322         toolspath = NULL;
1323     }
1324
1325     /* add the (empty) root node, if not already done */
1326     if(tap_menu_tree_root == NULL) {
1327         child = g_malloc0(sizeof (menu_item_t));
1328         tap_menu_tree_root = g_list_append(NULL, child);
1329     }
1330
1331     /*
1332      * Create any submenus required.
1333      */
1334     curnode = tap_menu_tree_root;
1335     p = name;
1336     while ((p = strchr(p, '/')) != NULL) {
1337         /*
1338          * OK, everything between "name" and "p" is
1339          * a menu relative subtree into which the menu item
1340          * will be placed.
1341          *
1342          * Construct the absolute path name of that subtree.
1343          */
1344         menupathlen = strlen(toolspath) + 1 + (p - name);
1345         menupath = g_malloc(menupathlen);
1346         g_strlcpy(menupath, toolspath, menupathlen);
1347         g_strlcat(menupath, name, menupathlen);
1348
1349         /*
1350          * Does there exist an entry with that path at this
1351          * level of the Analyze menu tree?
1352          */
1353         child = curnode->data;
1354         for (childnode = child->children; childnode != NULL; childnode = childnode->next) {
1355             child = childnode->data;
1356             if (strcmp(child->name, menupath) == 0)
1357                 break;
1358         }
1359         if (childnode == NULL) {
1360             /*
1361              * No.  Create such an item as a subtree, and
1362              * add it to the Tools menu tree.
1363              */
1364             childnode = tap_menu_item_add(
1365                 menupath, group, "", NULL, NULL ,NULL, NULL, curnode);
1366         } else {
1367             /*
1368              * Yes.  We don't need this "menupath" any longer.
1369              */
1370             g_free(menupath);
1371         }
1372         curnode = childnode;
1373
1374         /*
1375          * Skip over the '/' we found.
1376          */
1377         p++;
1378     }
1379
1380     /*
1381      * Construct the main menu path for the menu item.
1382      */
1383     menupathlen = strlen(toolspath) + 1 + strlen(name);
1384     menupath = g_malloc(menupathlen);
1385     g_strlcpy(menupath, toolspath, menupathlen);
1386     g_strlcat(menupath, name, menupathlen);
1387
1388     /*
1389      * Construct an item factory entry for the item, and add it to
1390      * the main menu.
1391      */
1392     tap_menu_item_add(
1393         menupath, group, stock_id, callback,
1394         selected_packet_enabled, selected_tree_row_enabled,
1395         callback_data, curnode);
1396 }
1397
1398
1399 void
1400 register_stat_menu_item(
1401     const char *name,
1402     register_stat_group_t group,
1403     GtkItemFactoryCallback callback,
1404     gboolean (*selected_packet_enabled)(frame_data *, epan_dissect_t *, gpointer callback_data),
1405     gboolean (*selected_tree_row_enabled)(field_info *, gpointer callback_data),
1406     gpointer callback_data)
1407 {
1408     register_stat_menu_item_stock(
1409         name,
1410         group,
1411         NULL,
1412         callback,
1413         selected_packet_enabled,
1414         selected_tree_row_enabled,
1415         callback_data);
1416 }
1417
1418 static guint merge_tap_menus_layered(GList *node, gint group) {
1419     GtkItemFactoryEntry *entry;
1420     GList       *child;
1421     guint       added = 0;
1422     menu_item_t *node_data = node->data;
1423
1424     /*
1425      * Is this a leaf node or an interior node?
1426      */
1427     if (node_data->children == NULL) {
1428         /*
1429          * It's a leaf node.
1430          */
1431
1432         /*
1433          * The root node doesn't correspond to a menu tree item; it
1434          * has a null name pointer.
1435          */
1436         if (node_data->name != NULL && group == node_data->group) {
1437             entry = g_malloc0(sizeof (GtkItemFactoryEntry));
1438             entry->path = node_data->name;
1439             entry->callback = node_data->callback;
1440             switch(group) {
1441             case(REGISTER_STAT_GROUP_UNSORTED):
1442                 break;
1443             case(REGISTER_STAT_GROUP_GENERIC):
1444                 break;
1445             case(REGISTER_STAT_GROUP_CONVERSATION_LIST):
1446                 entry->item_type = "<StockItem>";
1447                 entry->extra_data = WIRESHARK_STOCK_CONVERSATIONS;
1448                 break;
1449             case(REGISTER_STAT_GROUP_ENDPOINT_LIST):
1450                 entry->item_type = "<StockItem>";
1451                 entry->extra_data = WIRESHARK_STOCK_ENDPOINTS;
1452                 break;
1453             case(REGISTER_STAT_GROUP_RESPONSE_TIME):
1454                 entry->item_type = "<StockItem>";
1455                 entry->extra_data = WIRESHARK_STOCK_TIME;
1456                 break;
1457             case(REGISTER_STAT_GROUP_TELEPHONY):
1458                 break;
1459             case(REGISTER_ANALYZE_GROUP_UNSORTED):
1460                 break;
1461             case(REGISTER_ANALYZE_GROUP_CONVERSATION_FILTER):
1462                 break;
1463             case(REGISTER_TOOLS_GROUP_UNSORTED):
1464                 break;
1465             default:
1466                 g_assert_not_reached();
1467             }
1468             if(node_data->stock_id!= NULL) {
1469                 entry->item_type = "<StockItem>";
1470                 entry->extra_data = node_data->stock_id;
1471             }
1472             gtk_item_factory_create_item(main_menu_factory, entry, node_data->callback_data, /* callback_type */ 2);
1473             set_menu_sensitivity(main_menu_factory, node_data->name, FALSE); /* no capture file yet */
1474             added++;
1475             g_free(entry);
1476         }
1477     } else {
1478         /*
1479          * It's an interior node; call
1480          * "merge_tap_menus_layered()" on all its children
1481          */
1482
1483         /*
1484          * The root node doesn't correspond to a menu tree item; it
1485          * has a null name pointer.
1486          */
1487         if (node_data->name != NULL && group == node_data->group) {
1488             entry = g_malloc0(sizeof (GtkItemFactoryEntry));
1489             entry->path = node_data->name;
1490             entry->item_type = "<Branch>";
1491             gtk_item_factory_create_item(main_menu_factory, entry,
1492                 NULL, 2);
1493             set_menu_sensitivity(main_menu_factory, node_data->name,
1494                 FALSE);    /* no children yet */
1495             added++;
1496             g_free(entry);
1497         }
1498
1499         for (child = node_data->children; child != NULL; child =
1500             child->next) {
1501             added += merge_tap_menus_layered(child, group);
1502         }
1503     }
1504
1505     return added;
1506 }
1507
1508
1509 void merge_all_tap_menus(GList *node) {
1510     GtkItemFactoryEntry *sep_entry;
1511
1512     sep_entry = g_malloc0(sizeof (GtkItemFactoryEntry));
1513     sep_entry->item_type = "<Separator>";
1514     sep_entry->path = "/Statistics/";
1515
1516     /*
1517      * merge only the menu items of the specific group,
1518      * and then append a seperator
1519      */
1520     if (merge_tap_menus_layered(node, REGISTER_STAT_GROUP_GENERIC)) {
1521         gtk_item_factory_create_item(main_menu_factory, sep_entry, NULL, 2);
1522     }
1523     if (merge_tap_menus_layered(node, REGISTER_STAT_GROUP_CONVERSATION_LIST)) {
1524         /*gtk_item_factory_create_item(main_menu_factory, sep_entry, NULL, 2);*/
1525     }
1526     if (merge_tap_menus_layered(node, REGISTER_STAT_GROUP_ENDPOINT_LIST)) {
1527         /*gtk_item_factory_create_item(main_menu_factory, sep_entry, NULL, 2);*/
1528     }
1529     if (merge_tap_menus_layered(node, REGISTER_STAT_GROUP_RESPONSE_TIME)) {
1530         gtk_item_factory_create_item(main_menu_factory, sep_entry, NULL, 2);
1531     }
1532     if (merge_tap_menus_layered(node, REGISTER_STAT_GROUP_TELEPHONY)) {
1533         /*gtk_item_factory_create_item(main_menu_factory, sep_entry, NULL, 2);*/
1534     }
1535     if (merge_tap_menus_layered(node, REGISTER_STAT_GROUP_UNSORTED)) {
1536         /*gtk_item_factory_create_item(main_menu_factory, sep_entry, NULL, 2);*/
1537     }
1538     if (merge_tap_menus_layered(node, REGISTER_ANALYZE_GROUP_UNSORTED)) {
1539         sep_entry->path = "/Analyze/";
1540         /*gtk_item_factory_create_item(main_menu_factory, sep_entry, NULL, 2);*/
1541     }
1542     if (merge_tap_menus_layered(node, REGISTER_ANALYZE_GROUP_CONVERSATION_FILTER)) {
1543         sep_entry->path = "/Analyze/Conversation Filter/";
1544         /*gtk_item_factory_create_item(main_menu_factory, sep_entry, NULL, 2);*/
1545     }
1546     if (merge_tap_menus_layered(node, REGISTER_TOOLS_GROUP_UNSORTED)) {
1547         /*gtk_item_factory_create_item(main_menu_factory, sep_entry, NULL, 2);*/
1548     }
1549
1550     g_free (sep_entry);
1551 }
1552
1553
1554
1555 /*
1556  * Enable/disable menu sensitivity.
1557  */
1558 static void
1559 set_menu_sensitivity(GtkItemFactory *ifactory, const gchar *path, gint val)
1560 {
1561     GSList *menu_list;
1562     GtkWidget *menu_item;
1563     gchar *dup;
1564     gchar *dest;
1565
1566
1567     /* the underscore character regularly confuses things, as it will prevent finding
1568      * the menu_item, so it has to be removed first */
1569     dup = g_strdup(path);
1570     dest = dup;
1571     while(*path) {
1572         if (*path != '_') {
1573             *dest = *path;
1574             dest++;
1575         }
1576         path++;
1577     }
1578     *dest = '\0';
1579
1580     if (ifactory == NULL) {
1581         /*
1582          * Do it for all pop-up menus.
1583          */
1584         for (menu_list = popup_menu_list; menu_list != NULL;
1585              menu_list = g_slist_next(menu_list))
1586             set_menu_sensitivity(menu_list->data, dup, val);
1587     } else {
1588         /*
1589          * Do it for that particular menu.
1590          */
1591         if ((menu_item = gtk_item_factory_get_widget(ifactory, dup)) != NULL) {
1592             if (GTK_IS_MENU(menu_item)) {
1593                 /*
1594                  * "dup" refers to a submenu; "gtk_item_factory_get_widget()"
1595                  * gets the menu, not the item that, when selected, pops up
1596                  * the submenu.
1597                  *
1598                  * We have to change the latter item's sensitivity, so that
1599                  * it shows up normally if sensitive and grayed-out if
1600                  * insensitive.
1601                  */
1602                 menu_item = gtk_menu_get_attach_widget(GTK_MENU(menu_item));
1603             }
1604             gtk_widget_set_sensitive(menu_item, val);
1605         } else{
1606 #ifndef NEW_PACKET_LIST
1607             /* be sure this menu item *is* existing */
1608             g_assert_not_reached();
1609 #endif
1610         }
1611     }
1612
1613     g_free(dup);
1614 }
1615
1616 static void
1617 set_menu_object_data_meat(GtkItemFactory *ifactory, const gchar *path, const gchar *key, gpointer data)
1618 {
1619     GtkWidget *menu = NULL;
1620
1621     if ((menu = gtk_item_factory_get_widget(ifactory, path)) != NULL)
1622         g_object_set_data(G_OBJECT(menu), key, data);
1623 }
1624
1625 void
1626 set_menu_object_data (const gchar *path, const gchar *key, gpointer data) {
1627     GSList *menu_list = popup_menu_list;
1628     gchar *shortpath = strrchr(path, '/');
1629
1630     set_menu_object_data_meat(main_menu_factory, path, key, data);
1631     while (menu_list != NULL) {
1632         set_menu_object_data_meat(menu_list->data, shortpath, key, data);
1633         set_menu_object_data_meat(menu_list->data, path, key, data);
1634         menu_list = g_slist_next(menu_list);
1635     }
1636 }
1637
1638
1639 /* Recently used capture files submenu:
1640  * Submenu containing the recently used capture files.
1641  * The capture filenames are always kept with the absolute path, to be independant
1642  * of the current path.
1643  * They are only stored inside the labels of the submenu (no separate list). */
1644
1645 #define MENU_RECENT_FILES_PATH "/File/Open Recent"
1646 #define MENU_RECENT_FILES_KEY "Recent File Name"
1647
1648
1649
1650 static void
1651 update_menu_recent_capture_file1(GtkWidget *widget, gpointer cnt) {
1652     gchar *widget_cf_name;
1653
1654     widget_cf_name = g_object_get_data(G_OBJECT(widget), MENU_RECENT_FILES_KEY);
1655
1656     /* if this menu item is a file, count it */
1657     if (widget_cf_name) {
1658         (*(guint *)cnt)++;
1659         main_welcome_add_recent_capture_files(widget_cf_name);
1660     }
1661 }
1662
1663
1664
1665 /* update the menu */
1666 static void
1667 update_menu_recent_capture_file(GtkWidget *submenu_recent_files) {
1668     guint cnt = 0;
1669
1670
1671     main_welcome_reset_recent_capture_files();
1672
1673     gtk_container_foreach(GTK_CONTAINER(submenu_recent_files),
1674                           update_menu_recent_capture_file1, &cnt);
1675
1676     /* make parent menu item sensitive only, if we have any valid files in the list */
1677     set_menu_sensitivity(main_menu_factory, MENU_RECENT_FILES_PATH, cnt);
1678 }
1679
1680
1681
1682 /* remove the capture filename from the "Recent Files" menu */
1683 static void
1684 remove_menu_recent_capture_filename(gchar *cf_name) {
1685     GtkWidget *submenu_recent_files;
1686     GList* child_list;
1687     GList* child_list_item;
1688     GtkWidget    *menu_item_child;
1689     const gchar *menu_item_cf_name;
1690     
1691
1692     /* get the submenu container item */
1693     submenu_recent_files = gtk_item_factory_get_widget(main_menu_factory, MENU_RECENT_FILES_PATH);
1694
1695     /* find the corresponding menu item to be removed */
1696     child_list = gtk_container_get_children(GTK_CONTAINER(submenu_recent_files));
1697     child_list_item = child_list;
1698     while(child_list_item) {
1699         menu_item_child = (GTK_BIN(child_list_item->data))->child;
1700         if (menu_item_child != NULL) { /* Note: there are two "extra" items on the end of the child_list: */
1701                                        /*  - a separator (with no menu_item_child and thus no text label) */
1702                                        /*  - a 2nd item with a menu_child with text label "Clear"         */
1703                                        /*       [See add_menu_recent_capture_file_absolute() ]            */
1704                                        /* 'if (menu_item_child != NULL)' skips the separator item;        */
1705                                        /* An absolute filename in cf_name will never match  "Clear".      */
1706             menu_item_cf_name = gtk_label_get_text(GTK_LABEL(menu_item_child));
1707             if(strcmp(menu_item_cf_name, cf_name) == 0) {
1708                 /* XXX: is this all we need to do, to free the menu item and its label?
1709                    The reference count of widget will go to 0, so it'll be freed;
1710                    will that free the label? */
1711                 gtk_container_remove(GTK_CONTAINER(submenu_recent_files), child_list_item->data);
1712             }
1713         }
1714         child_list_item = g_list_next(child_list_item);
1715     }
1716     g_list_free(child_list);
1717
1718     update_menu_recent_capture_file(submenu_recent_files);
1719 }
1720
1721
1722 /* remove the capture filename from the "Recent Files" menu */
1723 static void
1724 remove_menu_recent_capture_file(GtkWidget *widget, gpointer unused _U_) {
1725     GtkWidget *submenu_recent_files;
1726     gchar *widget_cf_name;
1727
1728
1729     widget_cf_name = g_object_get_data(G_OBJECT(widget), MENU_RECENT_FILES_KEY);
1730     g_free(widget_cf_name);
1731
1732     /* get the submenu container item */
1733     submenu_recent_files = gtk_item_factory_get_widget(main_menu_factory, MENU_RECENT_FILES_PATH);
1734
1735     /* XXX: is this all we need to do, to free the menu item and its label?
1736        The reference count of widget will go to 0, so it'll be freed;
1737        will that free the label? */
1738     gtk_container_remove(GTK_CONTAINER(submenu_recent_files), widget);
1739 }
1740
1741
1742 /* callback, if the user pushed the <Clear> menu item */
1743 static void
1744 clear_menu_recent_capture_file_cmd_cb(GtkWidget *w _U_, gpointer unused _U_) {
1745     GtkWidget *submenu_recent_files;
1746
1747
1748     submenu_recent_files = gtk_item_factory_get_widget(main_menu_factory, MENU_RECENT_FILES_PATH);
1749
1750     gtk_container_foreach(GTK_CONTAINER(submenu_recent_files),
1751                           remove_menu_recent_capture_file, NULL);
1752
1753     update_menu_recent_capture_file(submenu_recent_files);
1754 }
1755
1756
1757 /* Open a file by it's name
1758    (Beware: will not ask to close existing capture file!) */
1759 void
1760 menu_open_filename(gchar *cf_name)
1761 {
1762     GtkWidget *submenu_recent_files;
1763     int       err;
1764
1765     submenu_recent_files = gtk_item_factory_get_widget(main_menu_factory, MENU_RECENT_FILES_PATH);
1766
1767     /* open and read the capture file (this will close an existing file) */
1768     if (cf_open(&cfile, cf_name, FALSE, &err) == CF_OK) {
1769         cf_read(&cfile);
1770     } else {
1771         /* the capture file apparently no longer exists; remove menu item    */
1772         /* XXX: ask user to remove item, it's maybe only a temporary problem */
1773         remove_menu_recent_capture_filename(cf_name);
1774     }
1775
1776     update_menu_recent_capture_file(submenu_recent_files);
1777 }
1778
1779
1780 /* callback, if the user pushed a recent file submenu item */
1781 void
1782 menu_open_recent_file_cmd(GtkWidget *w)
1783 {
1784     GtkWidget   *submenu_recent_files;
1785     GtkWidget   *menu_item_child;
1786     const gchar *cf_name;
1787     int         err;
1788
1789     submenu_recent_files = gtk_item_factory_get_widget(main_menu_factory, MENU_RECENT_FILES_PATH);
1790
1791     /* get capture filename from the menu item label */
1792     menu_item_child = (GTK_BIN(w))->child;
1793     cf_name = gtk_label_get_text(GTK_LABEL(menu_item_child));
1794
1795     /* open and read the capture file (this will close an existing file) */
1796     if (cf_open(&cfile, cf_name, FALSE, &err) == CF_OK) {
1797         cf_read(&cfile);
1798     } else {
1799         /* the capture file apparently no longer exists; remove menu item    */
1800         /* XXX: ask user to remove item, it's maybe only a temporary problem */
1801         remove_menu_recent_capture_file(w, NULL);
1802     }
1803
1804     update_menu_recent_capture_file(submenu_recent_files);
1805 }
1806
1807 static void menu_open_recent_file_answered_cb(gpointer dialog _U_, gint btn, gpointer data)
1808 {
1809     switch(btn) {
1810     case(ESD_BTN_YES):
1811         /* save file first */
1812         file_save_as_cmd(after_save_open_recent_file, data);
1813         break;
1814     case(ESD_BTN_NO):
1815         cf_close(&cfile);
1816         menu_open_recent_file_cmd(data);
1817         break;
1818     case(ESD_BTN_CANCEL):
1819         break;
1820     default:
1821         g_assert_not_reached();
1822     }
1823 }
1824
1825 static void
1826 menu_open_recent_file_cmd_cb(GtkWidget *widget, gpointer data _U_) {
1827     gpointer  dialog;
1828
1829
1830     if((cfile.state != FILE_CLOSED) && !cfile.user_saved && prefs.gui_ask_unsaved) {
1831         /* user didn't saved his current file, ask him */
1832         dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_YES_NO_CANCEL,
1833                                "%sSave capture file before opening a new one?%s\n\n"
1834                                "If you open a new capture file without saving, your current capture data will be discarded.",
1835                                simple_dialog_primary_start(), simple_dialog_primary_end());
1836         simple_dialog_set_cb(dialog, menu_open_recent_file_answered_cb, widget);
1837     } else {
1838         /* unchanged file */
1839         menu_open_recent_file_cmd(widget);
1840     }
1841 }
1842
1843 /* add the capture filename (with an absolute path) to the "Recent Files" menu */
1844 static void
1845 add_menu_recent_capture_file_absolute(gchar *cf_name) {
1846     GtkWidget *submenu_recent_files;
1847     GList *menu_item_list;
1848     GList *li;
1849     gchar *widget_cf_name;
1850     gchar *normalized_cf_name;
1851     GtkWidget *menu_item;
1852     guint cnt;
1853
1854
1855
1856     normalized_cf_name = g_strdup(cf_name);
1857 #ifdef _WIN32
1858     /* replace all slashes by backslashes */
1859     g_strdelimit(normalized_cf_name, "/", '\\');
1860 #endif
1861
1862     /* get the submenu container item */
1863     submenu_recent_files = gtk_item_factory_get_widget(main_menu_factory, MENU_RECENT_FILES_PATH);
1864
1865     /* convert container to a GList */
1866     menu_item_list = gtk_container_get_children(GTK_CONTAINER(submenu_recent_files));
1867
1868     /* iterate through list items of menu_item_list,
1869      * removing special items, a maybe duplicate entry and every item above count_max */
1870     cnt = 1;
1871     for (li = g_list_first(menu_item_list); li; li = li->next, cnt++) {
1872         /* get capture filename */
1873         menu_item = GTK_WIDGET(li->data);
1874         widget_cf_name = g_object_get_data(G_OBJECT(menu_item), MENU_RECENT_FILES_KEY);
1875
1876         /* if this element string is one of our special items (seperator, ...) or
1877          * already in the list or
1878          * this element is above maximum count (too old), remove it */
1879         if (!widget_cf_name ||
1880 #ifdef _WIN32
1881             /* do a case insensitive compare on win32 */
1882             g_ascii_strncasecmp(widget_cf_name, normalized_cf_name, 1000) == 0 ||
1883 #else   /* _WIN32 */
1884             /* do a case sensitive compare on unix */
1885             strncmp(widget_cf_name, normalized_cf_name, 1000) == 0 ||
1886 #endif
1887             cnt >= prefs.gui_recent_files_count_max) {
1888             remove_menu_recent_capture_file(li->data, NULL);
1889             cnt--;
1890         }
1891     }
1892
1893     g_list_free(menu_item_list);
1894
1895     /* add new item at latest position */
1896     menu_item = gtk_menu_item_new_with_label(normalized_cf_name);
1897     g_object_set_data(G_OBJECT(menu_item), MENU_RECENT_FILES_KEY, normalized_cf_name);
1898     gtk_menu_shell_prepend (GTK_MENU_SHELL(submenu_recent_files), menu_item);
1899     g_signal_connect_swapped(GTK_OBJECT(menu_item), "activate",
1900                              G_CALLBACK(menu_open_recent_file_cmd_cb), (GtkObject *) menu_item);
1901     gtk_widget_show (menu_item);
1902
1903     /* add seperator at last position */
1904     menu_item = gtk_menu_item_new();
1905     gtk_menu_shell_append (GTK_MENU_SHELL(submenu_recent_files), menu_item);
1906     gtk_widget_show (menu_item);
1907
1908     /* add new "clear list" item at last position */
1909     menu_item = gtk_image_menu_item_new_from_stock(GTK_STOCK_CLEAR, NULL);
1910     gtk_menu_shell_append (GTK_MENU_SHELL(submenu_recent_files), menu_item);
1911     g_signal_connect_swapped(GTK_OBJECT(menu_item), "activate",
1912                              G_CALLBACK(clear_menu_recent_capture_file_cmd_cb), (GtkObject *) menu_item);
1913     gtk_widget_show (menu_item);
1914
1915     update_menu_recent_capture_file(submenu_recent_files);
1916 }
1917
1918
1919 /* add the capture filename to the "Recent Files" menu */
1920 /* (will change nothing, if this filename is already in the menu) */
1921 /*
1922  * XXX - We might want to call SHAddToRecentDocs under Windows 7:
1923  * http://stackoverflow.com/questions/437212/how-do-you-register-a-most-recently-used-list-with-windows-in-preparation-for-win
1924  */
1925 void
1926 add_menu_recent_capture_file(gchar *cf_name) {
1927     gchar *curr;
1928     gchar *absolute;
1929
1930
1931     /* if this filename is an absolute path, we can use it directly */
1932     if (g_path_is_absolute(cf_name)) {
1933         add_menu_recent_capture_file_absolute(cf_name);
1934         return;
1935     }
1936
1937     /* this filename is not an absolute path, prepend the current dir */
1938     curr = g_get_current_dir();
1939     absolute = g_strdup_printf("%s%s%s", curr, G_DIR_SEPARATOR_S, cf_name);
1940     add_menu_recent_capture_file_absolute(absolute);
1941     g_free(curr);
1942     g_free(absolute);
1943 }
1944
1945
1946 /* write all capture filenames of the menu to the user's recent file */
1947 void
1948 menu_recent_file_write_all(FILE *rf) {
1949     GtkWidget   *submenu_recent_files;
1950     GList       *children;
1951     GList       *child;
1952     gchar       *cf_name;
1953
1954
1955     submenu_recent_files = gtk_item_factory_get_widget(main_menu_factory, MENU_RECENT_FILES_PATH);
1956
1957     /* we have to iterate backwards through the children's list,
1958      * so we get the latest item last in the file.
1959      * (don't use gtk_container_foreach() here, it will return the wrong iteration order) */
1960     children = gtk_container_get_children(GTK_CONTAINER(submenu_recent_files));
1961     child = g_list_last(children);
1962     while(child != NULL) {
1963         /* get capture filename from the menu item label */
1964         cf_name = g_object_get_data(G_OBJECT(child->data), MENU_RECENT_FILES_KEY);
1965         if (cf_name) {
1966             if(u3_active())
1967                 fprintf (rf, RECENT_KEY_CAPTURE_FILE ": %s\n", u3_contract_device_path(cf_name));
1968             else
1969                 fprintf (rf, RECENT_KEY_CAPTURE_FILE ": %s\n", cf_name);
1970         }
1971
1972         child = g_list_previous(child);
1973     }
1974
1975     g_list_free(children);
1976 }
1977
1978
1979 static void
1980 show_hide_cb(GtkWidget *w, gpointer data _U_, gint action)
1981 {
1982
1983     /* save current setting in recent */
1984     switch(action) {
1985         case(SHOW_HIDE_MAIN_TOOLBAR):
1986         recent.main_toolbar_show = GTK_CHECK_MENU_ITEM(w)->active;
1987         break;
1988         case(SHOW_HIDE_FILTER_TOOLBAR):
1989         recent.filter_toolbar_show = GTK_CHECK_MENU_ITEM(w)->active;
1990         break;
1991 #ifdef HAVE_AIRPCAP
1992         case(SHOW_HIDE_AIRPCAP_TOOLBAR):
1993         recent.airpcap_toolbar_show = GTK_CHECK_MENU_ITEM(w)->active;
1994         break;
1995 #endif
1996         case(SHOW_HIDE_STATUSBAR):
1997         recent.statusbar_show = GTK_CHECK_MENU_ITEM(w)->active;
1998         break;
1999         case(SHOW_HIDE_PACKET_LIST):
2000         recent.packet_list_show = GTK_CHECK_MENU_ITEM(w)->active;
2001         break;
2002         case(SHOW_HIDE_TREE_VIEW):
2003         recent.tree_view_show = GTK_CHECK_MENU_ITEM(w)->active;
2004         break;
2005         case(SHOW_HIDE_BYTE_VIEW):
2006         recent.byte_view_show = GTK_CHECK_MENU_ITEM(w)->active;
2007         break;
2008         default:
2009             g_assert_not_reached();
2010     }
2011
2012     main_widgets_show_or_hide();
2013 }
2014
2015
2016 static void
2017 timestamp_format_cb(GtkWidget *w _U_, gpointer d _U_, gint action)
2018 {
2019     if (recent.gui_time_format != action) {
2020         timestamp_set_type(action);
2021         recent.gui_time_format = action;
2022         cf_change_time_formats(&cfile);
2023     }
2024 }
2025
2026
2027 static void
2028 timestamp_precision_cb(GtkWidget *w _U_, gpointer d _U_, gint action)
2029 {
2030     if (recent.gui_time_precision != action) {
2031         /* the actual precision will be set in cf_change_time_formats() below */
2032         if (action == TS_PREC_AUTO) {
2033             timestamp_set_precision(TS_PREC_AUTO_SEC);
2034         } else {
2035             timestamp_set_precision(action);
2036         }
2037         recent.gui_time_precision  = action;
2038         cf_change_time_formats(&cfile);
2039     }
2040 }
2041
2042
2043 void
2044 menu_name_resolution_changed(void)
2045 {
2046     GtkWidget *menu = NULL;
2047
2048     menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Name Resolution/Enable for MAC Layer");
2049     gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), g_resolv_flags & RESOLV_MAC);
2050
2051     menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Name Resolution/Enable for Network Layer");
2052     gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), g_resolv_flags & RESOLV_NETWORK);
2053
2054     menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Name Resolution/Enable for Transport Layer");
2055     gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), g_resolv_flags & RESOLV_TRANSPORT);
2056 }
2057
2058 static void
2059 name_resolution_cb(GtkWidget *w, gpointer d _U_, gint action)
2060 {
2061     if (GTK_CHECK_MENU_ITEM(w)->active) {
2062         g_resolv_flags |= action;
2063     } else {
2064         g_resolv_flags &= ~action;
2065     }
2066 }
2067
2068 #ifdef HAVE_LIBPCAP
2069 void
2070 menu_auto_scroll_live_changed(gboolean auto_scroll_live_in) {
2071     GtkWidget *menu;
2072
2073
2074     /* tell menu about it */
2075     menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Auto Scroll in Live Capture");
2076     if( ((gboolean) GTK_CHECK_MENU_ITEM(menu)->active) != auto_scroll_live_in) {
2077         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), auto_scroll_live_in);
2078     }
2079
2080     /* tell toolbar about it */
2081     toolbar_auto_scroll_live_changed(auto_scroll_live_in);
2082
2083     /* change auto scroll */
2084     if(auto_scroll_live_in != auto_scroll_live) {
2085         auto_scroll_live  = auto_scroll_live_in;
2086     }
2087 }
2088
2089 static void
2090 auto_scroll_live_cb(GtkWidget *w _U_, gpointer d _U_)
2091 {
2092     menu_auto_scroll_live_changed(GTK_CHECK_MENU_ITEM(w)->active);
2093 }
2094 #endif
2095
2096
2097 void
2098 menu_colorize_changed(gboolean packet_list_colorize) {
2099     GtkWidget *menu;
2100
2101
2102     /* tell menu about it */
2103     menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Colorize Packet List");
2104     if( ((gboolean) GTK_CHECK_MENU_ITEM(menu)->active) != packet_list_colorize) {
2105         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), packet_list_colorize);
2106     }
2107
2108     /* tell toolbar about it */
2109     toolbar_colorize_changed(packet_list_colorize);
2110
2111     /* change colorization */
2112     if(packet_list_colorize != recent.packet_list_colorize) {
2113         recent.packet_list_colorize = packet_list_colorize;
2114         color_filters_enable(packet_list_colorize);
2115 #ifndef NEW_PACKET_LIST
2116         cf_colorize_packets(&cfile);
2117 #endif
2118     }
2119 }
2120
2121 static void
2122 colorize_cb(GtkWidget *w, gpointer d _U_)
2123 {
2124     menu_colorize_changed(GTK_CHECK_MENU_ITEM(w)->active);
2125 }
2126
2127
2128 /* the recent file read has finished, update the menu corresponding */
2129 void
2130 menu_recent_read_finished(void) {
2131     GtkWidget *menu = NULL;
2132
2133     menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Main Toolbar");
2134     gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), recent.main_toolbar_show);
2135
2136     menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Filter Toolbar");
2137     gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), recent.filter_toolbar_show);
2138
2139 #ifdef HAVE_AIRPCAP
2140     menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Wireless Toolbar");
2141     gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), recent.airpcap_toolbar_show);
2142 #endif
2143
2144     menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Statusbar");
2145     gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), recent.statusbar_show);
2146
2147     menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Packet List");
2148     gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), recent.packet_list_show);
2149
2150     menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Packet Details");
2151     gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), recent.tree_view_show);
2152
2153     menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Packet Bytes");
2154     gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), recent.byte_view_show);
2155
2156     menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Colorize Packet List");
2157     gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), recent.packet_list_colorize);
2158
2159     menu_name_resolution_changed();
2160
2161 #ifdef HAVE_LIBPCAP
2162     menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Auto Scroll in Live Capture");
2163     gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), auto_scroll_live);
2164 #endif
2165
2166     main_widgets_rearrange();
2167
2168     /* don't change the time format, if we had a command line value */
2169     if (timestamp_get_type() != TS_NOT_SET) {
2170         recent.gui_time_format = timestamp_get_type();
2171     }
2172
2173     switch(recent.gui_time_format) {
2174     case(TS_ABSOLUTE_WITH_DATE):
2175         menu = gtk_item_factory_get_widget(main_menu_factory,
2176             "/View/Time Display Format/Date and Time of Day:   1970-01-01 01:02:03.123456");
2177         /* set_active will not trigger the callback when activating an active item! */
2178         recent.gui_time_format = -1;
2179         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), FALSE);
2180         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), TRUE);
2181         break;
2182     case(TS_ABSOLUTE):
2183         menu = gtk_item_factory_get_widget(main_menu_factory,
2184             "/View/Time Display Format/Time of Day:   01:02:03.123456");
2185         /* set_active will not trigger the callback when activating an active item! */
2186         recent.gui_time_format = -1;
2187         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), TRUE);
2188         break;
2189     case(TS_RELATIVE):
2190         menu = gtk_item_factory_get_widget(main_menu_factory,
2191             "/View/Time Display Format/Seconds Since Beginning of Capture:   123.123456");
2192         recent.gui_time_format = -1;
2193         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), TRUE);
2194         break;
2195     case(TS_DELTA):
2196         menu = gtk_item_factory_get_widget(main_menu_factory,
2197             "/View/Time Display Format/Seconds Since Previous Captured Packet:   1.123456");
2198         recent.gui_time_format = -1;
2199         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), TRUE);
2200         break;
2201     case(TS_DELTA_DIS):
2202         menu = gtk_item_factory_get_widget(main_menu_factory,
2203             "/View/Time Display Format/Seconds Since Previous Displayed Packet:   1.123456");
2204         recent.gui_time_format = -1;
2205         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), TRUE);
2206         break;
2207     case(TS_EPOCH):
2208         menu = gtk_item_factory_get_widget(main_menu_factory,
2209             "/View/Time Display Format/Seconds Since Epoch (1970-01-01):   1234567890.123456");
2210         recent.gui_time_format = -1;
2211         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), TRUE);
2212         break;
2213     default:
2214         g_assert_not_reached();
2215     }
2216
2217     switch(recent.gui_time_precision) {
2218     case(TS_PREC_AUTO):
2219         menu = gtk_item_factory_get_widget(main_menu_factory,
2220             "/View/Time Display Format/Automatic (File Format Precision)");
2221         /* set_active will not trigger the callback when activating an active item! */
2222         recent.gui_time_precision = -1;
2223         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), FALSE);
2224         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), TRUE);
2225         break;
2226     case(TS_PREC_FIXED_SEC):
2227         menu = gtk_item_factory_get_widget(main_menu_factory,
2228             "/View/Time Display Format/Seconds:   0");
2229         recent.gui_time_precision = -1;
2230         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), TRUE);
2231         break;
2232     case(TS_PREC_FIXED_DSEC):
2233         menu = gtk_item_factory_get_widget(main_menu_factory,
2234             "/View/Time Display Format/Deciseconds:   0.1");
2235         recent.gui_time_precision = -1;
2236         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), TRUE);
2237         break;
2238     case(TS_PREC_FIXED_CSEC):
2239         menu = gtk_item_factory_get_widget(main_menu_factory,
2240             "/View/Time Display Format/Centiseconds:   0.12");
2241         recent.gui_time_precision = -1;
2242         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), TRUE);
2243         break;
2244     case(TS_PREC_FIXED_MSEC):
2245         menu = gtk_item_factory_get_widget(main_menu_factory,
2246             "/View/Time Display Format/Milliseconds:   0.123");
2247         recent.gui_time_precision = -1;
2248         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), TRUE);
2249         break;
2250     case(TS_PREC_FIXED_USEC):
2251         menu = gtk_item_factory_get_widget(main_menu_factory,
2252             "/View/Time Display Format/Microseconds:   0.123456");
2253         recent.gui_time_precision = -1;
2254         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), TRUE);
2255         break;
2256     case(TS_PREC_FIXED_NSEC):
2257         menu = gtk_item_factory_get_widget(main_menu_factory,
2258             "/View/Time Display Format/Nanoseconds:   0.123456789");
2259         recent.gui_time_precision = -1;
2260         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), TRUE);
2261         break;
2262     default:
2263         g_assert_not_reached();
2264     }
2265
2266     menu_colorize_changed(recent.packet_list_colorize);
2267 }
2268
2269
2270 #ifndef NEW_PACKET_LIST
2271 gint
2272 popup_menu_handler(GtkWidget *widget, GdkEvent *event, gpointer data)
2273 {
2274     GtkWidget *menu = (GtkWidget *)data;
2275     GdkEventButton *event_button = NULL;
2276     gint row, column;
2277
2278     if(widget == NULL || event == NULL || data == NULL) {
2279         return FALSE;
2280     }
2281
2282     /*
2283      * If we ever want to make the menu differ based on what row
2284      * and/or column we're above, we'd use "eth_clist_get_selection_info()"
2285      * to find the row and column number for the coordinates; a CTree is,
2286      * I guess, like a CList with one column(?) and the expander widget
2287      * as a pixmap.
2288      */
2289     /* Check if we are on packet_list object */
2290     if (widget == g_object_get_data(G_OBJECT(popup_menu_object), E_MPACKET_LIST_KEY) &&
2291         ((GdkEventButton *)event)->button != 1) {
2292         if (packet_list_get_event_row_column(widget, (GdkEventButton *)event,
2293                                              &row, &column)) {
2294             g_object_set_data(G_OBJECT(popup_menu_object), E_MPACKET_LIST_ROW_KEY,
2295                             GINT_TO_POINTER(row));
2296             g_object_set_data(G_OBJECT(popup_menu_object), E_MPACKET_LIST_COL_KEY,
2297                             GINT_TO_POINTER(column));
2298             packet_list_set_selected_row(row);
2299         }
2300     }
2301
2302     /* Check if we are on tree_view object */
2303     if (widget == tree_view) {
2304         tree_view_select(widget, (GdkEventButton *) event);
2305     }
2306
2307     /* Check if we are on byte_view object */
2308     if(widget == get_notebook_bv_ptr(byte_nb_ptr)) {
2309         byte_view_select(widget, (GdkEventButton *) event);
2310     }
2311
2312     /* context menu handler */
2313     if(event->type == GDK_BUTTON_PRESS) {
2314         event_button = (GdkEventButton *) event;
2315
2316         /* To qoute the "Gdk Event Structures" doc:
2317          * "Normally button 1 is the left mouse button, 2 is the middle button, and 3 is the right button" */
2318         if(event_button->button == 3) {
2319             /* No popup window in the byte view */
2320             if(widget != get_notebook_bv_ptr(byte_nb_ptr)) {
2321                 gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL,
2322                                event_button->button,
2323                                event_button->time);
2324             }
2325             g_signal_stop_emission_by_name(widget, "button_press_event");
2326             return TRUE;
2327         }
2328     }
2329     /* GDK_2BUTTON_PRESS is a doubleclick -> expand/collapse tree row */
2330     /* GTK version 1 seems to be doing this automatically */
2331     if (widget == tree_view && event->type == GDK_2BUTTON_PRESS) {
2332         GtkTreePath      *path;
2333
2334         if (gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(widget),
2335                                           (gint) (((GdkEventButton *)event)->x),
2336                                           (gint) (((GdkEventButton *)event)->y),
2337                                           &path, NULL, NULL, NULL))
2338         {
2339             if (gtk_tree_view_row_expanded(GTK_TREE_VIEW(widget), path))
2340                 gtk_tree_view_collapse_row(GTK_TREE_VIEW(widget), path);
2341             else
2342                 gtk_tree_view_expand_row(GTK_TREE_VIEW(widget), path,
2343                                          FALSE);
2344             gtk_tree_path_free(path);
2345         }
2346     }
2347     return FALSE;
2348 }
2349 #endif /* NEW_PACKET_LIST */
2350
2351 /* Enable or disable menu items based on whether you have a capture file
2352    you've finished reading and, if you have one, whether it's been saved
2353    and whether it could be saved except by copying the raw packet data. */
2354 void
2355 set_menus_for_capture_file(capture_file *cf)
2356 {
2357     if (cf == NULL) {
2358         /* We have no capture file */
2359         set_menu_sensitivity(main_menu_factory, "/File/Merge...", FALSE);
2360         set_menu_sensitivity(main_menu_factory, "/File/Close", FALSE);
2361         set_menu_sensitivity(main_menu_factory, "/File/Save", FALSE);
2362         set_menu_sensitivity(main_menu_factory, "/File/Save As...", FALSE);
2363         set_menu_sensitivity(main_menu_factory, "/File/Export", FALSE);
2364         set_menu_sensitivity(main_menu_factory, "/View/Reload", FALSE);
2365         set_toolbar_for_capture_file(FALSE);
2366         set_toolbar_for_unsaved_capture_file(FALSE);
2367     } else {
2368         set_menu_sensitivity(main_menu_factory, "/File/Merge...", TRUE);
2369         set_menu_sensitivity(main_menu_factory, "/File/Close", TRUE);
2370         set_menu_sensitivity(main_menu_factory, "/File/Save", !cf->user_saved);
2371         /*
2372          * "Save As..." works only if we can write the file out in at least
2373          * one format (so we can save the whole file or just a subset) or
2374          * if we have an unsaved capture (so writing the whole file out
2375          * with a raw data copy makes sense).
2376          */
2377         set_menu_sensitivity(main_menu_factory, "/File/Save As...",
2378                              cf_can_save_as(cf) || !cf->user_saved);
2379         set_menu_sensitivity(main_menu_factory, "/File/Export", TRUE);
2380         set_menu_sensitivity(main_menu_factory, "/View/Reload", TRUE);
2381         set_toolbar_for_unsaved_capture_file(!cf->user_saved);
2382         set_toolbar_for_capture_file(TRUE);
2383     }
2384 }
2385
2386 /* Enable or disable menu items based on whether there's a capture in
2387    progress. */
2388 void
2389 set_menus_for_capture_in_progress(gboolean capture_in_progress)
2390 {
2391     set_menu_sensitivity(main_menu_factory, "/File/Open...",
2392                          !capture_in_progress);
2393     set_menu_sensitivity(main_menu_factory, "/File/Open Recent",
2394                          !capture_in_progress);
2395     set_menu_sensitivity(main_menu_factory, "/File/Export",
2396                          capture_in_progress);
2397 #ifdef HAVE_LIBPCAP
2398     set_menu_sensitivity(main_menu_factory, "/Capture/Options...",
2399                          !capture_in_progress);
2400     set_menu_sensitivity(main_menu_factory, "/Capture/Start",
2401                          !capture_in_progress);
2402     set_menu_sensitivity(main_menu_factory, "/Capture/Stop",
2403                          capture_in_progress);
2404     set_menu_sensitivity(main_menu_factory, "/Capture/Restart",
2405                          capture_in_progress);
2406     set_toolbar_for_capture_in_progress(capture_in_progress);
2407
2408     set_capture_if_dialog_for_capture_in_progress(capture_in_progress);
2409 #endif /* HAVE_LIBPCAP */
2410 }
2411
2412 /* Enable or disable menu items based on whether you have some captured
2413    packets. */
2414 static gboolean
2415 walk_menu_tree_for_captured_packets(GList *node,
2416     gboolean have_captured_packets)
2417 {
2418     gboolean    is_enabled;
2419     GList       *child;
2420     menu_item_t *node_data = node->data;
2421
2422     /*
2423      * Is this a leaf node or an interior node?
2424      */
2425     if (node_data->children == NULL) {
2426         /*
2427          * It's a leaf node.
2428          *
2429          * If it has no "selected_packet_enabled()" or
2430          * "selected_tree_row_enabled()" routines, we enable
2431          * it.  This allows tap windows to be popped up even
2432          * if you have no capture file; this is done to let
2433          * the user pop up multiple tap windows before reading
2434          * in a capture file, so that they can be processed in
2435          * parallel while the capture file is being read rather
2436          * than one at at time as you pop up the windows, and to
2437          * let the user pop up tap windows before starting an
2438          * "Update list of packets in real time" capture, so that
2439          * the statistics can be displayed while the capture is
2440          * in progress.
2441          *
2442          * If it has either of those routines, we disable it for
2443          * now - as long as, when a capture is first available,
2444          * we don't get called after a packet or tree row is
2445          * selected, that's OK.
2446          * XXX - that should be done better.
2447          */
2448         if (node_data->selected_packet_enabled == NULL &&
2449             node_data->selected_tree_row_enabled == NULL)
2450             node_data->enabled = TRUE;
2451         else
2452             node_data->enabled = FALSE;
2453     } else {
2454         /*
2455          * It's an interior node; call
2456          * "walk_menu_tree_for_captured_packets()" on all its
2457          * children and, if any of them are enabled, enable
2458          * this node, otherwise disable it.
2459          *
2460          * XXX - should we just leave all interior nodes enabled?
2461          * Which is a better UI choice?
2462          */
2463         is_enabled = FALSE;
2464         for (child = node_data->children; child != NULL; child =
2465                  child->next) {
2466             if (walk_menu_tree_for_captured_packets(child,
2467                                                     have_captured_packets))
2468                 is_enabled = TRUE;
2469         }
2470         node_data->enabled = is_enabled;
2471     }
2472
2473     /*
2474      * The root node doesn't correspond to a menu tree item; it
2475      * has a null name pointer.
2476      */
2477     if (node_data->name != NULL) {
2478         set_menu_sensitivity(main_menu_factory, node_data->name,
2479                              node_data->enabled);
2480     }
2481     return node_data->enabled;
2482 }
2483
2484 void
2485 set_menus_for_captured_packets(gboolean have_captured_packets)
2486 {
2487     set_menu_sensitivity(main_menu_factory, "/File/Print...",
2488                          have_captured_packets);
2489     set_menu_sensitivity(packet_list_menu_factory, "/Print...",
2490                          have_captured_packets);
2491     set_menu_sensitivity(main_menu_factory, "/Edit/Find Packet...",
2492                          have_captured_packets);
2493     set_menu_sensitivity(main_menu_factory, "/Edit/Find Next",
2494                          have_captured_packets);
2495     set_menu_sensitivity(main_menu_factory, "/Edit/Find Previous",
2496                          have_captured_packets);
2497     set_menu_sensitivity(main_menu_factory, "/View/Zoom In",
2498                          have_captured_packets);
2499     set_menu_sensitivity(main_menu_factory, "/View/Zoom Out",
2500                          have_captured_packets);
2501     set_menu_sensitivity(main_menu_factory, "/View/Normal Size",
2502                          have_captured_packets);
2503     set_menu_sensitivity(main_menu_factory, "/Go/Go to Packet...",
2504                          have_captured_packets);
2505     set_menu_sensitivity(main_menu_factory, "/Go/Previous Packet",
2506                          have_captured_packets);
2507     set_menu_sensitivity(main_menu_factory, "/Go/Next Packet",
2508                          have_captured_packets);
2509     set_menu_sensitivity(main_menu_factory, "/Go/First Packet",
2510                          have_captured_packets);
2511     set_menu_sensitivity(main_menu_factory, "/Go/Last Packet",
2512                          have_captured_packets);
2513     set_menu_sensitivity(main_menu_factory, "/Statistics/Summary",
2514                          have_captured_packets);
2515     set_menu_sensitivity(main_menu_factory, "/Statistics/Protocol Hierarchy",
2516                          have_captured_packets);
2517
2518     walk_menu_tree_for_captured_packets(tap_menu_tree_root,
2519                                         have_captured_packets);
2520     set_toolbar_for_captured_packets(have_captured_packets);
2521 }
2522
2523 /* Enable or disable menu items based on whether a packet is selected and,
2524    if so, on the properties of the packet. */
2525 static gboolean
2526 walk_menu_tree_for_selected_packet(GList *node, frame_data *fd,
2527     epan_dissect_t *edt)
2528 {
2529     gboolean is_enabled;
2530     GList *child;
2531     menu_item_t *node_data = node->data;
2532
2533     /*
2534      * Is this a leaf node or an interior node?
2535      */
2536     if (node_data->children == NULL) {
2537         /*
2538          * It's a leaf node.
2539          *
2540          * If it has no "selected_packet_enabled()" routine,
2541          * leave its enabled/disabled status alone - it
2542          * doesn't depend on whether we have a packet selected
2543          * or not or on the selected packet.
2544          *
2545          * If it has a "selected_packet_enabled()" routine,
2546          * call it and set the item's enabled/disabled status
2547          * based on its return value.
2548          */
2549         if (node_data->selected_packet_enabled != NULL)
2550             node_data->enabled = node_data->selected_packet_enabled(fd, edt, node_data->callback_data);
2551     } else {
2552         /*
2553          * It's an interior node; call
2554          * "walk_menu_tree_for_selected_packet()" on all its
2555          * children and, if any of them are enabled, enable
2556          * this node, otherwise disable it.
2557          *
2558          * XXX - should we just leave all interior nodes enabled?
2559          * Which is a better UI choice?
2560          */
2561         is_enabled = FALSE;
2562         for (child = node_data->children; child != NULL; child =
2563                  child->next) {
2564             if (walk_menu_tree_for_selected_packet(child, fd, edt))
2565                 is_enabled = TRUE;
2566         }
2567         node_data->enabled = is_enabled;
2568     }
2569
2570     /*
2571      * The root node doesn't correspond to a menu tree item; it
2572      * has a null name pointer.
2573      */
2574     if (node_data->name != NULL) {
2575         set_menu_sensitivity(main_menu_factory, node_data->name,
2576                              node_data->enabled);
2577     }
2578     return node_data->enabled;
2579 }
2580
2581 gboolean
2582 packet_is_ssl(epan_dissect_t* edt)
2583 {
2584     GPtrArray* array;
2585     int ssl_id;
2586     gboolean is_ssl;
2587
2588     if (!edt || !edt->tree)
2589         return FALSE;
2590     ssl_id = proto_get_id_by_filter_name("ssl");
2591     if (ssl_id < 0)
2592         return FALSE;
2593     array = proto_find_finfo(edt->tree, ssl_id);
2594     is_ssl = (array->len > 0) ? TRUE : FALSE;
2595     g_ptr_array_free(array, FALSE);
2596     return is_ssl;
2597 }
2598
2599 void
2600 set_menus_for_selected_packet(capture_file *cf)
2601 {
2602     gboolean is_ssl = packet_is_ssl(cf->edt);
2603     set_menu_sensitivity(main_menu_factory, "/Edit/Mark Packet (toggle)",
2604                          cf->current_frame != NULL);
2605     set_menu_sensitivity(packet_list_menu_factory, "/Mark Packet (toggle)",
2606                          cf->current_frame != NULL);
2607     set_menu_sensitivity(main_menu_factory, "/Edit/Find Next Mark",
2608                          cf->current_frame != NULL);
2609     set_menu_sensitivity(main_menu_factory, "/Edit/Find Previous Mark",
2610                          cf->current_frame != NULL);
2611     set_menu_sensitivity(main_menu_factory, "/Edit/Mark All Packets",
2612                          cf->current_frame != NULL);
2613     set_menu_sensitivity(main_menu_factory, "/Edit/Unmark All Packets",
2614                          cf->current_frame != NULL);
2615     set_menu_sensitivity(main_menu_factory, "/Edit/Set Time Reference (toggle)",
2616                          cf->current_frame != NULL);
2617     set_menu_sensitivity(packet_list_menu_factory, "/Set Time Reference (toggle)",
2618                          cf->current_frame != NULL);
2619     set_menu_sensitivity(main_menu_factory, "/Edit/Find Next Reference",
2620                          cf->current_frame != NULL);
2621     set_menu_sensitivity(main_menu_factory, "/Edit/Find Previous Reference",
2622                          cf->current_frame != NULL);
2623     set_menu_sensitivity(main_menu_factory, "/View/Resize All Columns",
2624                          cf->current_frame != NULL);
2625     set_menu_sensitivity(main_menu_factory, "/View/Collapse All",
2626                          cf->current_frame != NULL);
2627     set_menu_sensitivity(tree_view_menu_factory, "/Collapse All",
2628                          cf->current_frame != NULL);
2629     set_menu_sensitivity(main_menu_factory, "/View/Expand All",
2630                          cf->current_frame != NULL);
2631     set_menu_sensitivity(tree_view_menu_factory, "/Expand All",
2632                          cf->current_frame != NULL);
2633     set_menu_sensitivity(main_menu_factory, "/View/Colorize Conversation",
2634                          cf->current_frame != NULL);
2635     set_menu_sensitivity(main_menu_factory, "/View/Reset Coloring 1-10",
2636                          tmp_color_filters_used());
2637     set_menu_sensitivity(main_menu_factory, "/View/Show Packet in New Window",
2638                          cf->current_frame != NULL);
2639     set_menu_sensitivity(packet_list_menu_factory, "/Show Packet in New Window",
2640                          cf->current_frame != NULL);
2641     set_menu_sensitivity(packet_list_menu_factory, "/SCTP",
2642                          cf->current_frame != NULL ? (cf->edt->pi.ipproto == IP_PROTO_SCTP) : FALSE);
2643     set_menu_sensitivity(main_menu_factory, "/Analyze/Follow TCP Stream",
2644                          cf->current_frame != NULL ? (cf->edt->pi.ipproto == IP_PROTO_TCP) : FALSE);
2645     set_menu_sensitivity(packet_list_menu_factory, "/Follow TCP Stream",
2646                          cf->current_frame != NULL ? (cf->edt->pi.ipproto == IP_PROTO_TCP) : FALSE);
2647     set_menu_sensitivity(tree_view_menu_factory, "/Follow TCP Stream",
2648                          cf->current_frame != NULL ? (cf->edt->pi.ipproto == IP_PROTO_TCP) : FALSE);
2649     set_menu_sensitivity(main_menu_factory, "/Analyze/Follow UDP Stream",
2650                          cf->current_frame != NULL ? (cf->edt->pi.ipproto == IP_PROTO_UDP) : FALSE);
2651     set_menu_sensitivity(packet_list_menu_factory, "/Follow UDP Stream",
2652                          cf->current_frame != NULL ? (cf->edt->pi.ipproto == IP_PROTO_UDP) : FALSE);
2653     set_menu_sensitivity(tree_view_menu_factory, "/Follow UDP Stream",
2654                          cf->current_frame != NULL ? (cf->edt->pi.ipproto == IP_PROTO_UDP) : FALSE);
2655     set_menu_sensitivity(main_menu_factory, "/Analyze/Follow SSL Stream",
2656                          cf->current_frame != NULL ? is_ssl : FALSE);
2657     set_menu_sensitivity(packet_list_menu_factory, "/Follow SSL Stream",
2658                          cf->current_frame != NULL ? is_ssl : FALSE);
2659     set_menu_sensitivity(tree_view_menu_factory, "/Follow SSL Stream",
2660                          cf->current_frame != NULL ? is_ssl : FALSE);
2661     set_menu_sensitivity(packet_list_menu_factory, "/Conversation Filter",
2662                          cf->current_frame != NULL);
2663     set_menu_sensitivity(packet_list_menu_factory, "/Conversation Filter/Ethernet",
2664                          cf->current_frame != NULL ? (cf->edt->pi.dl_src.type == AT_ETHER) : FALSE);
2665     set_menu_sensitivity(packet_list_menu_factory, "/Conversation Filter/IP",
2666                          cf->current_frame != NULL ? ((cf->edt->pi.ethertype == ETHERTYPE_IP)||(cf->edt->pi.ethertype == ETHERTYPE_IPv6)) : FALSE);
2667     set_menu_sensitivity(packet_list_menu_factory, "/Conversation Filter/TCP",
2668                          cf->current_frame != NULL ? (cf->edt->pi.ipproto == IP_PROTO_TCP) : FALSE);
2669     set_menu_sensitivity(packet_list_menu_factory, "/Conversation Filter/UDP",
2670                          cf->current_frame != NULL ? (cf->edt->pi.ipproto == IP_PROTO_UDP) : FALSE);
2671     set_menu_sensitivity(packet_list_menu_factory, "/Conversation Filter/PN-CBA Server",
2672                          cf->current_frame != NULL ? (cf->edt->pi.profinet_type != 0 && cf->edt->pi.profinet_type < 10) : FALSE);
2673     set_menu_sensitivity(packet_list_menu_factory, "/Colorize Conversation",
2674                          cf->current_frame != NULL);
2675     set_menu_sensitivity(packet_list_menu_factory, "/Colorize Conversation/Ethernet",
2676                          cf->current_frame != NULL ? (cf->edt->pi.dl_src.type == AT_ETHER) : FALSE);
2677     set_menu_sensitivity(packet_list_menu_factory, "/Colorize Conversation/IP",
2678                          cf->current_frame != NULL ? ((cf->edt->pi.ethertype == ETHERTYPE_IP)||(cf->edt->pi.ethertype == ETHERTYPE_IPv6)) : FALSE);
2679     set_menu_sensitivity(packet_list_menu_factory, "/Colorize Conversation/TCP",
2680                          cf->current_frame != NULL ? (cf->edt->pi.ipproto == IP_PROTO_TCP) : FALSE);
2681     set_menu_sensitivity(packet_list_menu_factory, "/Colorize Conversation/UDP",
2682                          cf->current_frame != NULL ? (cf->edt->pi.ipproto == IP_PROTO_UDP) : FALSE);
2683     set_menu_sensitivity(packet_list_menu_factory, "/Colorize Conversation/PN-CBA Server",
2684                          cf->current_frame != NULL ? (cf->edt->pi.profinet_type != 0 && cf->edt->pi.profinet_type < 10) : FALSE);
2685     set_menu_sensitivity(main_menu_factory, "/Analyze/Decode As...",
2686                          cf->current_frame != NULL && decode_as_ok());
2687     set_menu_sensitivity(packet_list_menu_factory, "/Decode As...",
2688                          cf->current_frame != NULL && decode_as_ok());
2689     set_menu_sensitivity(tree_view_menu_factory, "/Decode As...",
2690                          cf->current_frame != NULL && decode_as_ok());
2691     set_menu_sensitivity(main_menu_factory, "/View/Name Resolution/Resolve Name",
2692                          cf->current_frame != NULL && (g_resolv_flags & RESOLV_ALL_ADDRS) != RESOLV_ALL_ADDRS);
2693     set_menu_sensitivity(tree_view_menu_factory, "/Resolve Name",
2694                          cf->current_frame != NULL && (g_resolv_flags & RESOLV_ALL_ADDRS) != RESOLV_ALL_ADDRS);
2695     set_menu_sensitivity(packet_list_menu_factory, "/Copy",
2696                          cf->current_frame != NULL);
2697     set_menu_sensitivity(packet_list_menu_factory, "/Apply as Filter",
2698                          cf->current_frame != NULL);
2699     set_menu_sensitivity(packet_list_menu_factory, "/Prepare a Filter",
2700                          cf->current_frame != NULL);
2701     set_menu_sensitivity(main_menu_factory, "/Tools/Firewall ACL Rules",
2702                          cf->current_frame != NULL);
2703
2704     walk_menu_tree_for_selected_packet(tap_menu_tree_root, cf->current_frame,
2705                                        cf->edt);
2706 }
2707
2708 /* Enable or disable menu items based on whether a tree row is selected
2709    and, if so, on the properties of the tree row. */
2710 static gboolean
2711 walk_menu_tree_for_selected_tree_row(GList *node, field_info *fi)
2712 {
2713     gboolean is_enabled;
2714     GList *child;
2715     menu_item_t *node_data = node->data;
2716
2717     /*
2718      * Is this a leaf node or an interior node?
2719      */
2720     if (node_data->children == NULL) {
2721         /*
2722          * It's a leaf node.
2723          *
2724          * If it has no "selected_tree_row_enabled()" routine,
2725          * leave its enabled/disabled status alone - it
2726          * doesn't depend on whether we have a tree row selected
2727          * or not or on the selected tree row.
2728          *
2729          * If it has a "selected_tree_row_enabled()" routine,
2730          * call it and set the item's enabled/disabled status
2731          * based on its return value.
2732          */
2733         if (node_data->selected_tree_row_enabled != NULL)
2734             node_data->enabled = node_data->selected_tree_row_enabled(fi, node_data->callback_data);
2735     } else {
2736         /*
2737          * It's an interior node; call
2738          * "walk_menu_tree_for_selected_tree_row()" on all its
2739          * children and, if any of them are enabled, enable
2740          * this node, otherwise disable it.
2741          *
2742          * XXX - should we just leave all interior nodes enabled?
2743          * Which is a better UI choice?
2744          */
2745         is_enabled = FALSE;
2746         for (child = node_data->children; child != NULL; child =
2747                  child->next) {
2748             if (walk_menu_tree_for_selected_tree_row(child, fi))
2749                 is_enabled = TRUE;
2750         }
2751         node_data->enabled = is_enabled;
2752     }
2753
2754     /*
2755      * The root node doesn't correspond to a menu tree item; it
2756      * has a null name pointer.
2757      */
2758     if (node_data->name != NULL) {
2759         set_menu_sensitivity(main_menu_factory, node_data->name,
2760                              node_data->enabled);
2761     }
2762     return node_data->enabled;
2763 }
2764
2765 static void
2766 menu_prefs_toggle_bool (GtkWidget *w, gpointer data)
2767 {
2768     gboolean *value = data;
2769     module_t *module = g_object_get_data (G_OBJECT(w), "module");
2770
2771     module->prefs_changed = TRUE;
2772     *value = !(*value);
2773
2774     prefs_apply (module);
2775     if (!prefs.gui_use_pref_save) {
2776         prefs_main_write();
2777     }
2778     redissect_packets();
2779 }
2780
2781 static void
2782 menu_prefs_change_enum (GtkWidget *w, gpointer data)
2783 {
2784     gint *value = data;
2785     module_t *module = g_object_get_data (G_OBJECT(w), "module");
2786     gint new_value = GPOINTER_TO_INT(g_object_get_data (G_OBJECT(w), "enumval"));
2787
2788     if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM(w)))
2789         return;
2790
2791     if (*value != new_value) {
2792         module->prefs_changed = TRUE;
2793         *value = new_value;
2794
2795         prefs_apply (module);
2796         if (!prefs.gui_use_pref_save) {
2797             prefs_main_write();
2798         }
2799         redissect_packets();
2800     }
2801 }
2802
2803 void
2804 menu_prefs_reset(void)
2805 {
2806         g_free (g_object_get_data(G_OBJECT(tree_view_menu_factory), "menu_abbrev"));
2807         g_object_set_data(G_OBJECT(tree_view_menu_factory), "menu_abbrev", NULL);
2808 }
2809
2810 static void
2811 menu_prefs_change_ok (GtkWidget *w, gpointer parent_w)
2812 {
2813     GtkWidget *entry = g_object_get_data (G_OBJECT(w), "entry");
2814     module_t *module = g_object_get_data (G_OBJECT(w), "module");
2815     pref_t *pref = g_object_get_data (G_OBJECT(w), "pref");
2816     const gchar *new_value =  gtk_entry_get_text(GTK_ENTRY(entry));
2817     range_t *newrange;
2818     gchar *p;
2819     guint uval;
2820
2821     switch (pref->type) {
2822     case PREF_UINT:
2823         uval = strtoul(new_value, &p, pref->info.base);
2824         if (p == new_value || *p != '\0') {
2825             simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2826                           "The value \"%s\" isn't a valid number.",
2827                           new_value);
2828             return;
2829         }
2830         if (*pref->varp.uint != uval) {
2831             module->prefs_changed = TRUE;
2832             *pref->varp.uint = uval;
2833         }
2834         break;
2835     case PREF_STRING:
2836         if (strcmp (*pref->varp.string, new_value) != 0) {
2837             module->prefs_changed = TRUE;
2838             g_free((void*)*pref->varp.string);
2839             *pref->varp.string = g_strdup(new_value);
2840         }
2841         break;
2842     case PREF_RANGE:
2843         if (range_convert_str(&newrange, new_value, pref->info.max_value) != CVT_NO_ERROR) {
2844             simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2845                           "The value \"%s\" isn't a valid range.",
2846                           new_value);
2847             return;
2848         }
2849         if (!ranges_are_equal(*pref->varp.range, newrange)) {
2850             module->prefs_changed = TRUE;
2851             g_free(*pref->varp.range);
2852             *pref->varp.range = newrange;
2853         } else {
2854             g_free (newrange);
2855         }
2856         break;
2857     default:
2858         g_assert_not_reached();
2859         break;
2860     }
2861
2862     if (module->prefs_changed) {
2863         /* Ensure we reload the sub menu */
2864         menu_prefs_reset();
2865         prefs_apply (module);
2866         if (!prefs.gui_use_pref_save) {
2867             prefs_main_write();
2868         }
2869         redissect_packets();
2870     }
2871
2872     window_destroy(GTK_WIDGET(parent_w));
2873 }
2874
2875 static void
2876 menu_prefs_change_cancel (GtkWidget *w _U_, gpointer parent_w)
2877 {
2878     window_destroy(GTK_WIDGET(parent_w));
2879 }
2880
2881 static void 
2882 menu_prefs_edit_dlg (GtkWidget *w, gpointer data)
2883 {
2884     pref_t *pref = data;
2885     module_t *module = g_object_get_data (G_OBJECT(w), "module");
2886     gchar *value = NULL;
2887
2888     GtkWidget *win, *main_tb, *main_vb, *bbox, *cancel_bt, *ok_bt;
2889     GtkWidget *entry, *label;
2890     GtkTooltips *tooltips;
2891
2892     switch (pref->type) {
2893     case PREF_UINT:
2894         switch (pref->info.base) {
2895         case 8:
2896             value = g_strdup_printf("%o", *pref->varp.uint);
2897             break;
2898         case 10:
2899             value = g_strdup_printf("%u", *pref->varp.uint);
2900             break;
2901         case 16:
2902             value = g_strdup_printf("%x", *pref->varp.uint);
2903             break;
2904         default:
2905             g_assert_not_reached();
2906             break;
2907         }
2908         break;
2909     case PREF_STRING:
2910         value = g_strdup(*pref->varp.string);
2911         break;
2912     case PREF_RANGE:
2913         value = g_strdup(range_convert_range (*pref->varp.range));
2914         break;
2915     default:
2916         g_assert_not_reached();
2917         break;
2918     }
2919
2920     tooltips = gtk_tooltips_new();
2921
2922     win = dlg_window_new(module->description);
2923
2924     gtk_window_set_resizable(GTK_WINDOW(win),FALSE);
2925     gtk_window_resize(GTK_WINDOW(win), 400, 100);
2926
2927     main_vb = gtk_vbox_new(FALSE, 5);
2928     gtk_container_add(GTK_CONTAINER(win), main_vb);
2929     gtk_container_set_border_width(GTK_CONTAINER(main_vb), 6);
2930
2931     main_tb = gtk_table_new(2, 2, FALSE);
2932     gtk_box_pack_start(GTK_BOX(main_vb), main_tb, FALSE, FALSE, 0);
2933     gtk_table_set_col_spacings(GTK_TABLE(main_tb), 10);
2934
2935     label = gtk_label_new(ep_strdup_printf("%s:", pref->title));
2936     gtk_table_attach_defaults(GTK_TABLE(main_tb), label, 0, 1, 1, 2);
2937     gtk_misc_set_alignment(GTK_MISC(label), 1.0f, 0.5f);
2938     if (pref->description)
2939         gtk_tooltips_set_tip(tooltips, label, pref->description, NULL);
2940
2941     entry = gtk_entry_new();
2942     gtk_table_attach_defaults(GTK_TABLE(main_tb), entry, 1, 2, 1, 2);
2943     gtk_entry_set_text(GTK_ENTRY(entry), value);
2944     if (pref->description)
2945         gtk_tooltips_set_tip(tooltips, entry, pref->description, NULL);
2946
2947     bbox = dlg_button_row_new(GTK_STOCK_CANCEL,GTK_STOCK_OK, NULL);
2948     gtk_box_pack_end(GTK_BOX(main_vb), bbox, FALSE, FALSE, 0);
2949
2950     ok_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_OK);
2951     g_object_set_data (G_OBJECT(ok_bt), "module", module);
2952     g_object_set_data (G_OBJECT(ok_bt), "entry", entry);
2953     g_object_set_data (G_OBJECT(ok_bt), "pref", pref);
2954     g_signal_connect(ok_bt, "clicked", G_CALLBACK(menu_prefs_change_ok), win);
2955
2956     dlg_set_activate(entry, ok_bt);
2957
2958     cancel_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_CANCEL);
2959     g_signal_connect(cancel_bt, "clicked", G_CALLBACK(menu_prefs_change_cancel), win);
2960     window_set_cancel_button(win, cancel_bt, NULL);
2961
2962     gtk_widget_grab_default(ok_bt);
2963     gtk_widget_show_all(win);
2964     g_free(value);
2965 }
2966
2967 static guint
2968 add_protocol_prefs_menu (pref_t *pref, gpointer data)
2969 {
2970     GtkWidget *menu_preferences;
2971     GtkWidget *menu_item, *menu_sub_item, *sub_menu;
2972     GSList *group = NULL;
2973     module_t *module = data;
2974     const enum_val_t *enum_valp;
2975     gchar *label = NULL;
2976
2977     switch (pref->type) {
2978     case PREF_UINT:
2979         switch (pref->info.base) {
2980         case 8:
2981             label = g_strdup_printf ("%s: %o", pref->title, *pref->varp.uint);
2982             break;
2983         case 10:
2984             label = g_strdup_printf ("%s: %u", pref->title, *pref->varp.uint);
2985             break;
2986         case 16:
2987             label = g_strdup_printf ("%s: %x", pref->title, *pref->varp.uint);
2988             break;
2989         default:
2990             g_assert_not_reached();
2991             break;
2992         }
2993         menu_item = gtk_menu_item_new_with_label(label);
2994         g_object_set_data (G_OBJECT(menu_item), "module", module);
2995         g_signal_connect(menu_item, "activate", G_CALLBACK(menu_prefs_edit_dlg), pref);
2996         g_free (label);
2997         break;
2998     case PREF_BOOL:
2999         menu_item = gtk_check_menu_item_new_with_label(pref->title);
3000         gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM(menu_item), *pref->varp.boolp);
3001         g_object_set_data (G_OBJECT(menu_item), "module", module);
3002         g_signal_connect(menu_item, "activate", G_CALLBACK(menu_prefs_toggle_bool), pref->varp.boolp);
3003         break;
3004     case PREF_ENUM:
3005         menu_item = gtk_menu_item_new_with_label(pref->title);
3006         sub_menu = gtk_menu_new();
3007         gtk_menu_item_set_submenu (GTK_MENU_ITEM(menu_item), sub_menu);
3008         enum_valp = pref->info.enum_info.enumvals;
3009         while (enum_valp->name != NULL) {
3010             menu_sub_item = gtk_radio_menu_item_new_with_label(group, enum_valp->description);
3011             group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (menu_sub_item));
3012             if (enum_valp->value == *pref->varp.enump) {
3013                 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM(menu_sub_item), TRUE);
3014             }
3015             g_object_set_data (G_OBJECT(menu_sub_item), "module", module);
3016             g_object_set_data (G_OBJECT(menu_sub_item), "enumval", GINT_TO_POINTER(enum_valp->value));
3017             g_signal_connect(menu_sub_item, "activate", G_CALLBACK(menu_prefs_change_enum), pref->varp.enump);
3018             gtk_menu_shell_append (GTK_MENU_SHELL(sub_menu), menu_sub_item);
3019             gtk_widget_show (menu_sub_item);
3020             enum_valp++;
3021         }
3022         break;
3023     case PREF_STRING:
3024         label = g_strdup_printf ("%s: %s", pref->title, *pref->varp.string);
3025         menu_item = gtk_menu_item_new_with_label(label);
3026         g_object_set_data (G_OBJECT(menu_item), "module", module);
3027         g_signal_connect(menu_item, "activate", G_CALLBACK(menu_prefs_edit_dlg), pref);
3028         g_free (label);
3029         break;
3030     case PREF_RANGE:
3031         label = g_strdup_printf ("%s: %s", pref->title, range_convert_range (*pref->varp.range));
3032         menu_item = gtk_menu_item_new_with_label(label);
3033         g_object_set_data (G_OBJECT(menu_item), "module", module);
3034         g_signal_connect(menu_item, "activate", G_CALLBACK(menu_prefs_edit_dlg), pref);
3035         g_free (label);
3036         break;
3037     case PREF_UAT:
3038         label = g_strdup_printf ("%s...", pref->title);
3039         menu_item = gtk_menu_item_new_with_label(label);
3040         g_signal_connect (menu_item, "activate", G_CALLBACK(uat_window_cb), pref->varp.uat);
3041         g_free (label);
3042         break;
3043     case PREF_STATIC_TEXT:
3044     case PREF_OBSOLETE:
3045     default:
3046         /* Nothing to add */
3047         return 0;
3048     }
3049
3050     menu_preferences = gtk_item_factory_get_widget(tree_view_menu_factory, "/Protocol Preferences");
3051     sub_menu = gtk_menu_item_get_submenu (GTK_MENU_ITEM(menu_preferences));
3052     gtk_menu_shell_append (GTK_MENU_SHELL(sub_menu), menu_item);
3053     gtk_widget_show (menu_item);
3054
3055     return 0;
3056 }
3057
3058 static void
3059 rebuild_protocol_prefs_menu (module_t *prefs, gboolean preferences)
3060 {
3061     GtkWidget *menu_preferences, *menu_item;
3062     GtkWidget *sub_menu;
3063     gchar *label;
3064
3065     menu_preferences = gtk_item_factory_get_widget(tree_view_menu_factory, "/Protocol Preferences");
3066
3067     if (preferences) {
3068         sub_menu = gtk_menu_new();
3069         gtk_menu_item_set_submenu (GTK_MENU_ITEM(menu_preferences), sub_menu);
3070
3071         label = g_strdup_printf ("%s Preferences...", prefs->description);
3072         menu_item = gtk_image_menu_item_new_with_label (label);
3073         gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM(menu_item), 
3074                                        gtk_image_new_from_stock(GTK_STOCK_PREFERENCES, GTK_ICON_SIZE_MENU));
3075         gtk_menu_shell_append (GTK_MENU_SHELL(sub_menu), menu_item);
3076         g_signal_connect_swapped(GTK_OBJECT(menu_item), "activate",
3077                                  G_CALLBACK(properties_cb), (GtkObject *) menu_item);
3078         gtk_widget_show (menu_item);
3079         g_free (label);
3080
3081         menu_item = gtk_menu_item_new();
3082         gtk_menu_shell_append (GTK_MENU_SHELL(sub_menu), menu_item);
3083         gtk_widget_show (menu_item);
3084
3085         prefs_pref_foreach(prefs, add_protocol_prefs_menu, prefs);
3086     } else {
3087         /* No preferences, remove sub menu */
3088         gtk_menu_item_set_submenu (GTK_MENU_ITEM(menu_preferences), NULL);
3089     }
3090
3091 }
3092
3093 void
3094 set_menus_for_selected_tree_row(capture_file *cf)
3095 {
3096     gboolean properties;
3097     gint id;
3098
3099     if (cf->finfo_selected != NULL) {
3100         header_field_info *hfinfo = cf->finfo_selected->hfinfo;
3101         const char *abbrev;
3102         char *prev_abbrev;
3103
3104         if (hfinfo->parent == -1) {
3105             abbrev = hfinfo->abbrev;
3106             id = (hfinfo->type == FT_PROTOCOL) ? proto_get_id((protocol_t *)hfinfo->strings) : -1;
3107         } else {
3108             abbrev = proto_registrar_get_abbrev(hfinfo->parent);
3109             id = hfinfo->parent;
3110         }
3111         properties = prefs_is_registered_protocol(abbrev);
3112
3113         set_menu_sensitivity(main_menu_factory,
3114                              "/File/Export/Selected Packet Bytes...", TRUE);
3115         set_menu_sensitivity(main_menu_factory,
3116                              "/Go/Go to Corresponding Packet", hfinfo->type == FT_FRAMENUM);
3117         set_menu_sensitivity(tree_view_menu_factory,
3118                              "/Go to Corresponding Packet", hfinfo->type == FT_FRAMENUM);
3119         set_menu_sensitivity(main_menu_factory, "/Edit/Copy/Description",
3120                              proto_can_match_selected(cf->finfo_selected, cf->edt));
3121         set_menu_sensitivity(main_menu_factory, "/Edit/Copy/Fieldname",
3122                              proto_can_match_selected(cf->finfo_selected, cf->edt));
3123         set_menu_sensitivity(main_menu_factory, "/Edit/Copy/Value",
3124                              proto_can_match_selected(cf->finfo_selected, cf->edt));
3125         set_menu_sensitivity(main_menu_factory, "/Edit/Copy/As Filter",
3126                              proto_can_match_selected(cf->finfo_selected, cf->edt));
3127         set_menu_sensitivity(tree_view_menu_factory, "/Copy",
3128                              TRUE);
3129         set_menu_sensitivity(tree_view_menu_factory, "/Copy/As Filter",
3130                              proto_can_match_selected(cf->finfo_selected, cf->edt));
3131         set_menu_sensitivity(main_menu_factory, "/Analyze/Apply as Filter",
3132                              proto_can_match_selected(cf->finfo_selected, cf->edt));
3133         set_menu_sensitivity(tree_view_menu_factory, "/Apply as Filter",
3134                              proto_can_match_selected(cf->finfo_selected, cf->edt));
3135         set_menu_sensitivity(main_menu_factory, "/Analyze/Prepare a Filter",
3136                              proto_can_match_selected(cf->finfo_selected, cf->edt));
3137         set_menu_sensitivity(tree_view_menu_factory, "/Prepare a Filter",
3138                              proto_can_match_selected(cf->finfo_selected, cf->edt));
3139         set_menu_sensitivity(tree_view_menu_factory, "/Colorize with Filter",
3140                              proto_can_match_selected(cf->finfo_selected, cf->edt));
3141         set_menu_sensitivity(tree_view_menu_factory, "/Protocol Preferences",
3142                              properties);
3143         set_menu_sensitivity(tree_view_menu_factory, "/Disable Protocol...",
3144                              (id == -1) ? FALSE : proto_can_toggle_protocol(id));
3145         set_menu_sensitivity(main_menu_factory, "/View/Expand Subtrees", cf->finfo_selected->tree_type != -1);
3146         set_menu_sensitivity(tree_view_menu_factory, "/Expand Subtrees", cf->finfo_selected->tree_type != -1);
3147         set_menu_sensitivity(tree_view_menu_factory, "/Wiki Protocol Page",
3148                              TRUE);
3149         set_menu_sensitivity(tree_view_menu_factory, "/Filter Field Reference",
3150                              TRUE);
3151         
3152         prev_abbrev = g_object_get_data(G_OBJECT(tree_view_menu_factory), "menu_abbrev");
3153         if (!prev_abbrev || (strcmp (prev_abbrev, abbrev) != 0)) {
3154             /* No previous protocol or protocol changed - update Protocol Preferences menu */
3155             module_t *prefs = prefs_find_module(abbrev);
3156             rebuild_protocol_prefs_menu (prefs, properties);
3157
3158             g_object_set_data(G_OBJECT(tree_view_menu_factory), "menu_abbrev", g_strdup(abbrev));
3159             g_free (prev_abbrev);
3160         }
3161     } else {
3162         set_menu_sensitivity(main_menu_factory,
3163                              "/File/Export/Selected Packet Bytes...", FALSE);
3164         set_menu_sensitivity(main_menu_factory,
3165                              "/Go/Go to Corresponding Packet", FALSE);
3166         set_menu_sensitivity(tree_view_menu_factory,
3167                              "/Go to Corresponding Packet", FALSE);
3168         set_menu_sensitivity(main_menu_factory, "/Edit/Copy/Description", FALSE);
3169         set_menu_sensitivity(main_menu_factory, "/Edit/Copy/Fieldname", FALSE);
3170         set_menu_sensitivity(main_menu_factory, "/Edit/Copy/Value", FALSE);
3171         set_menu_sensitivity(main_menu_factory, "/Edit/Copy/As Filter", FALSE);
3172         set_menu_sensitivity(tree_view_menu_factory, "/Copy", FALSE);
3173         set_menu_sensitivity(main_menu_factory, "/Analyze/Apply as Filter", FALSE);
3174         set_menu_sensitivity(tree_view_menu_factory, "/Apply as Filter", FALSE);
3175         set_menu_sensitivity(main_menu_factory, "/Analyze/Prepare a Filter", FALSE);
3176         set_menu_sensitivity(tree_view_menu_factory, "/Prepare a Filter", FALSE);
3177         set_menu_sensitivity(tree_view_menu_factory, "/Colorize with Filter", FALSE);
3178         set_menu_sensitivity(tree_view_menu_factory, "/Protocol Preferences",
3179                              FALSE);
3180         set_menu_sensitivity(tree_view_menu_factory, "/Disable Protocol...", FALSE);
3181         set_menu_sensitivity(main_menu_factory, "/View/Expand Subtrees", FALSE);
3182         set_menu_sensitivity(tree_view_menu_factory, "/Expand Subtrees", FALSE);
3183         set_menu_sensitivity(tree_view_menu_factory, "/Wiki Protocol Page",
3184                              FALSE);
3185         set_menu_sensitivity(tree_view_menu_factory, "/Filter Field Reference",
3186                              FALSE);
3187     }
3188
3189     walk_menu_tree_for_selected_tree_row(tap_menu_tree_root, cf->finfo_selected);
3190 }
3191
3192 void set_menus_for_packet_history(gboolean back_history, gboolean forward_history) {
3193
3194     set_menu_sensitivity(main_menu_factory, "/Go/Back", back_history);
3195     set_menu_sensitivity(main_menu_factory, "/Go/Forward", forward_history);
3196
3197     set_toolbar_for_packet_history(back_history, forward_history);
3198 }
3199
3200
3201 void set_menus_for_file_set(gboolean file_set, gboolean previous_file, gboolean next_file) {
3202
3203     set_menu_sensitivity(main_menu_factory, "/File/File Set/List Files", file_set);
3204     set_menu_sensitivity(main_menu_factory, "/File/File Set/Previous File", previous_file);
3205     set_menu_sensitivity(main_menu_factory, "/File/File Set/Next File", next_file);
3206 }
3207
3208 /*
3209  * Editor modelines
3210  *
3211  * Local Variables:
3212  * c-basic-offset: 4
3213  * tab-width: 8
3214  * indent-tabs-mode: nil
3215  * End:
3216  *
3217  * ex: set shiftwidth=4 tabstop=8 expandtab
3218  * :indentSize=4:tabSize=8:noTabs=true:
3219  */
3220