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