187cf492c7cbf167f20ed6c59552218dcfc77d91
[obnox/wireshark/wip.git] / gtk / main_menu.c
1 /* main_menu.c
2  * Main menu routines
3  *
4  * $Id$
5  *
6  * Wireshark - Network traffic analyzer
7  * By Gerald Combs <gerald@wireshark.org>
8  * Copyright 1998 Gerald Combs
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License
12  * as published by the Free Software Foundation; either version 2
13  * of the License, or (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
23  */
24
25 #ifdef HAVE_CONFIG_H
26 # include "config.h"
27 #endif
28
29 #include <gtk/gtk.h>
30
31 #include <string.h>
32
33 #include <epan/packet.h>
34 #include <epan/addr_resolv.h>
35 #include <epan/prefs.h>
36 #include <epan/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/main_menu.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     /* popup */
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     tree_view_menu_factory = gtk_item_factory_new(GTK_TYPE_MENU, "<main>", NULL);
1167     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);
1168     g_object_set_data(G_OBJECT(popup_menu_object), PM_TREE_VIEW_KEY,
1169                     tree_view_menu_factory->widget);
1170     popup_menu_list = g_slist_append((GSList *)popup_menu_list, tree_view_menu_factory);
1171
1172     hexdump_menu_factory = gtk_item_factory_new(GTK_TYPE_MENU, "<main>", NULL);
1173     g_object_set_data(G_OBJECT(popup_menu_object), PM_HEXDUMP_KEY,
1174                     hexdump_menu_factory->widget);
1175     popup_menu_list = g_slist_append((GSList *)popup_menu_list, hexdump_menu_factory);
1176     /* main */
1177     main_menu_factory = gtk_item_factory_new(GTK_TYPE_MENU_BAR, "<main>", grp);
1178     gtk_item_factory_create_items_ac(main_menu_factory, nmenu_items, menu_items, NULL, 2);
1179
1180     menu_dissector_filter();
1181     merge_all_tap_menus(tap_menu_tree_root);
1182
1183     /* Initialize enabled/disabled state of menu items */
1184     set_menus_for_capture_file(NULL);
1185 #if 0
1186     /* Un-#if this when we actually implement Cut/Copy/Paste.
1187        Then make sure you enable them when they can be done. */
1188     set_menu_sensitivity(main_menu_factory, "/Edit/Cut", FALSE);
1189     set_menu_sensitivity(main_menu_factory, "/Edit/Copy", FALSE);
1190     set_menu_sensitivity(main_menu_factory, "/Edit/Paste", FALSE);
1191 #endif
1192
1193     set_menus_for_captured_packets(FALSE);
1194     set_menus_for_selected_packet(&cfile);
1195     set_menus_for_selected_tree_row(&cfile);
1196     set_menus_for_capture_in_progress(FALSE);
1197     set_menus_for_file_set(/* dialog */TRUE, /* previous file */ FALSE, /* next_file */ FALSE);
1198
1199     /* init with an empty recent files list */
1200     clear_menu_recent_capture_file_cmd_cb(NULL, NULL);
1201
1202     }
1203 }
1204
1205
1206 static gint tap_menu_item_add_compare(gconstpointer a, gconstpointer b)
1207 {
1208     return strcmp(
1209         ((const menu_item_t *) a)->name,
1210         ((const menu_item_t *) b)->name);
1211 }
1212
1213
1214 /* add a menuitem below the current node */
1215 static GList * tap_menu_item_add(
1216     char *name,
1217     gint group,
1218     const char *stock_id,
1219     GtkItemFactoryCallback callback,
1220     gboolean (*selected_packet_enabled)(frame_data *, epan_dissect_t *, gpointer callback_data),
1221     gboolean (*selected_tree_row_enabled)(field_info *, gpointer callback_data),
1222     gpointer callback_data,
1223     GList *curnode)
1224 {
1225     menu_item_t *curr;
1226     menu_item_t *child;
1227
1228
1229     child = g_malloc(sizeof (menu_item_t));
1230     child->name             = name;
1231     child->group            = group;
1232     child->stock_id         = stock_id;
1233     child->callback         = callback;
1234     child->selected_packet_enabled = selected_packet_enabled;
1235     child->selected_tree_row_enabled = selected_tree_row_enabled;
1236     child->callback_data    = callback_data;
1237     child->enabled          = FALSE;
1238     child->children         = NULL;
1239
1240     /* insert the new child node into the parent */
1241     curr = curnode->data;
1242     curr->children = g_list_insert_sorted(curr->children, child, tap_menu_item_add_compare);
1243
1244     /* return the new node */
1245     /* XXX: improve this */
1246     return g_list_find(curr->children, child);
1247 }
1248
1249 /*
1250  * Add a new menu item for a tap.
1251  * This must be called after we've created the main menu, so it can't
1252  * be called from the routine that registers taps - we have to introduce
1253  * another per-tap registration routine.
1254  *
1255  * "callback" gets called when the menu item is selected; it should do
1256  * the work of creating the tap window.
1257  *
1258  * "selected_packet_enabled" gets called by "set_menus_for_selected_packet()";
1259  * it's passed a Boolean that's TRUE if a packet is selected and FALSE
1260  * otherwise, and should return TRUE if the tap will work now (which
1261  * might depend on whether a packet is selected and, if one is, on the
1262  * packet) and FALSE if not.
1263  *
1264  * "selected_tree_row_enabled" gets called by
1265  * "set_menus_for_selected_tree_row()"; it's passed a Boolean that's TRUE if
1266  * a protocol tree row is selected and FALSE otherwise, and should return
1267  * TRUE if the tap will work now (which might depend on whether a tree row
1268  * is selected and, if one is, on the tree row) and FALSE if not.
1269  */
1270 void
1271 register_stat_menu_item_stock(
1272     const char *name,
1273     register_stat_group_t group,
1274     const char *stock_id,
1275     GtkItemFactoryCallback callback,
1276     gboolean (*selected_packet_enabled)(frame_data *, epan_dissect_t *, gpointer callback_data),
1277     gboolean (*selected_tree_row_enabled)(field_info *, gpointer callback_data),
1278     gpointer callback_data)
1279 {
1280     /*static const char toolspath[] = "/Statistics/";*/
1281     const char *toolspath;
1282     const char *p;
1283     char *menupath;
1284     size_t menupathlen;
1285     menu_item_t *child;
1286     GList *curnode;
1287     GList *childnode;
1288
1289     /*
1290      * The menu path must be relative.
1291      */
1292     g_assert(*name != '/');
1293
1294     switch(group) {
1295     case(REGISTER_STAT_GROUP_GENERIC): toolspath = "/Statistics/"; break;
1296     case(REGISTER_STAT_GROUP_CONVERSATION_LIST): toolspath = "/Statistics/_Conversation List/"; break;
1297     case(REGISTER_STAT_GROUP_ENDPOINT_LIST): toolspath = "/Statistics/_Endpoint List/"; break;
1298     case(REGISTER_STAT_GROUP_RESPONSE_TIME): toolspath = "/Statistics/Service _Response Time/"; break;
1299     case(REGISTER_STAT_GROUP_UNSORTED): toolspath = "/Statistics/"; break;
1300     case(REGISTER_ANALYZE_GROUP_UNSORTED): toolspath = "/Analyze/"; break;
1301     case(REGISTER_ANALYZE_GROUP_CONVERSATION_FILTER): toolspath = "/Analyze/Conversation Filter/"; break;
1302     case(REGISTER_STAT_GROUP_TELEPHONY): toolspath = "/Telephony/"; break;
1303     case(REGISTER_TOOLS_GROUP_UNSORTED): toolspath = "/Tools/"; break;
1304     default:
1305         g_assert(!"no such menu group");
1306         toolspath = NULL;
1307     }
1308
1309     /* add the (empty) root node, if not already done */
1310     if(tap_menu_tree_root == NULL) {
1311         child = g_malloc0(sizeof (menu_item_t));
1312         tap_menu_tree_root = g_list_append(NULL, child);
1313     }
1314
1315     /*
1316      * Create any submenus required.
1317      */
1318     curnode = tap_menu_tree_root;
1319     p = name;
1320     while ((p = strchr(p, '/')) != NULL) {
1321         /*
1322          * OK, everything between "name" and "p" is
1323          * a menu relative subtree into which the menu item
1324          * will be placed.
1325          *
1326          * Construct the absolute path name of that subtree.
1327          */
1328         menupathlen = strlen(toolspath) + 1 + (p - name);
1329         menupath = g_malloc(menupathlen);
1330         g_strlcpy(menupath, toolspath, menupathlen);
1331         g_strlcat(menupath, name, menupathlen);
1332
1333         /*
1334          * Does there exist an entry with that path at this
1335          * level of the Analyze menu tree?
1336          */
1337         child = curnode->data;
1338         for (childnode = child->children; childnode != NULL; childnode = childnode->next) {
1339             child = childnode->data;
1340             if (strcmp(child->name, menupath) == 0)
1341                 break;
1342         }
1343         if (childnode == NULL) {
1344             /*
1345              * No.  Create such an item as a subtree, and
1346              * add it to the Tools menu tree.
1347              */
1348             childnode = tap_menu_item_add(
1349                 menupath, group, "", NULL, NULL ,NULL, NULL, curnode);
1350         } else {
1351             /*
1352              * Yes.  We don't need this "menupath" any longer.
1353              */
1354             g_free(menupath);
1355         }
1356         curnode = childnode;
1357
1358         /*
1359          * Skip over the '/' we found.
1360          */
1361         p++;
1362     }
1363
1364     /*
1365      * Construct the main menu path for the menu item.
1366      */
1367     menupathlen = strlen(toolspath) + 1 + strlen(name);
1368     menupath = g_malloc(menupathlen);
1369     g_strlcpy(menupath, toolspath, menupathlen);
1370     g_strlcat(menupath, name, menupathlen);
1371
1372     /*
1373      * Construct an item factory entry for the item, and add it to
1374      * the main menu.
1375      */
1376     tap_menu_item_add(
1377         menupath, group, stock_id, callback,
1378         selected_packet_enabled, selected_tree_row_enabled,
1379         callback_data, curnode);
1380 }
1381
1382
1383 void
1384 register_stat_menu_item(
1385     const char *name,
1386     register_stat_group_t group,
1387     GtkItemFactoryCallback callback,
1388     gboolean (*selected_packet_enabled)(frame_data *, epan_dissect_t *, gpointer callback_data),
1389     gboolean (*selected_tree_row_enabled)(field_info *, gpointer callback_data),
1390     gpointer callback_data)
1391 {
1392     register_stat_menu_item_stock(
1393         name,
1394         group,
1395         NULL,
1396         callback,
1397         selected_packet_enabled,
1398         selected_tree_row_enabled,
1399         callback_data);
1400 }
1401
1402 static guint merge_tap_menus_layered(GList *node, gint group) {
1403     GtkItemFactoryEntry *entry;
1404     GList       *child;
1405     guint       added = 0;
1406     menu_item_t *node_data = node->data;
1407
1408     /*
1409      * Is this a leaf node or an interior node?
1410      */
1411     if (node_data->children == NULL) {
1412         /*
1413          * It's a leaf node.
1414          */
1415
1416         /*
1417          * The root node doesn't correspond to a menu tree item; it
1418          * has a null name pointer.
1419          */
1420         if (node_data->name != NULL && group == node_data->group) {
1421             entry = g_malloc0(sizeof (GtkItemFactoryEntry));
1422             entry->path = node_data->name;
1423             entry->callback = node_data->callback;
1424             switch(group) {
1425             case(REGISTER_STAT_GROUP_UNSORTED):
1426                 break;
1427             case(REGISTER_STAT_GROUP_GENERIC):
1428                 break;
1429             case(REGISTER_STAT_GROUP_CONVERSATION_LIST):
1430                 entry->item_type = "<StockItem>";
1431                 entry->extra_data = WIRESHARK_STOCK_CONVERSATIONS;
1432                 break;
1433             case(REGISTER_STAT_GROUP_ENDPOINT_LIST):
1434                 entry->item_type = "<StockItem>";
1435                 entry->extra_data = WIRESHARK_STOCK_ENDPOINTS;
1436                 break;
1437             case(REGISTER_STAT_GROUP_RESPONSE_TIME):
1438                 entry->item_type = "<StockItem>";
1439                 entry->extra_data = WIRESHARK_STOCK_TIME;
1440                 break;
1441             case(REGISTER_STAT_GROUP_TELEPHONY):
1442                 break;
1443             case(REGISTER_ANALYZE_GROUP_UNSORTED):
1444                 break;
1445             case(REGISTER_ANALYZE_GROUP_CONVERSATION_FILTER):
1446                 break;
1447             case(REGISTER_TOOLS_GROUP_UNSORTED):
1448                 break;
1449             default:
1450                 g_assert_not_reached();
1451             }
1452             if(node_data->stock_id!= NULL) {
1453                 entry->item_type = "<StockItem>";
1454                 entry->extra_data = node_data->stock_id;
1455             }
1456             gtk_item_factory_create_item(main_menu_factory, entry, node_data->callback_data, /* callback_type */ 2);
1457             set_menu_sensitivity(main_menu_factory, node_data->name, FALSE); /* no capture file yet */
1458             added++;
1459             g_free(entry);
1460         }
1461     } else {
1462         /*
1463          * It's an interior node; call
1464          * "merge_tap_menus_layered()" on all its children
1465          */
1466
1467         /*
1468          * The root node doesn't correspond to a menu tree item; it
1469          * has a null name pointer.
1470          */
1471         if (node_data->name != NULL && group == node_data->group) {
1472             entry = g_malloc0(sizeof (GtkItemFactoryEntry));
1473             entry->path = node_data->name;
1474             entry->item_type = "<Branch>";
1475             gtk_item_factory_create_item(main_menu_factory, entry,
1476                 NULL, 2);
1477             set_menu_sensitivity(main_menu_factory, node_data->name,
1478                 FALSE);    /* no children yet */
1479             added++;
1480             g_free(entry);
1481         }
1482
1483         for (child = node_data->children; child != NULL; child =
1484             child->next) {
1485             added += merge_tap_menus_layered(child, group);
1486         }
1487     }
1488
1489     return added;
1490 }
1491
1492
1493 void merge_all_tap_menus(GList *node) {
1494     GtkItemFactoryEntry *sep_entry;
1495
1496     sep_entry = g_malloc0(sizeof (GtkItemFactoryEntry));
1497     sep_entry->item_type = "<Separator>";
1498     sep_entry->path = "/Statistics/";
1499
1500     /*
1501      * merge only the menu items of the specific group,
1502      * and then append a seperator
1503      */
1504     if (merge_tap_menus_layered(node, REGISTER_STAT_GROUP_GENERIC)) {
1505         gtk_item_factory_create_item(main_menu_factory, sep_entry, NULL, 2);
1506     }
1507     if (merge_tap_menus_layered(node, REGISTER_STAT_GROUP_CONVERSATION_LIST)) {
1508         /*gtk_item_factory_create_item(main_menu_factory, sep_entry, NULL, 2);*/
1509     }
1510     if (merge_tap_menus_layered(node, REGISTER_STAT_GROUP_ENDPOINT_LIST)) {
1511         /*gtk_item_factory_create_item(main_menu_factory, sep_entry, NULL, 2);*/
1512     }
1513     if (merge_tap_menus_layered(node, REGISTER_STAT_GROUP_RESPONSE_TIME)) {
1514         gtk_item_factory_create_item(main_menu_factory, sep_entry, NULL, 2);
1515     }
1516     if (merge_tap_menus_layered(node, REGISTER_STAT_GROUP_TELEPHONY)) {
1517         /*gtk_item_factory_create_item(main_menu_factory, sep_entry, NULL, 2);*/
1518     }
1519     if (merge_tap_menus_layered(node, REGISTER_STAT_GROUP_UNSORTED)) {
1520         /*gtk_item_factory_create_item(main_menu_factory, sep_entry, NULL, 2);*/
1521     }
1522     if (merge_tap_menus_layered(node, REGISTER_ANALYZE_GROUP_UNSORTED)) {
1523         sep_entry->path = "/Analyze/";
1524         /*gtk_item_factory_create_item(main_menu_factory, sep_entry, NULL, 2);*/
1525     }
1526     if (merge_tap_menus_layered(node, REGISTER_ANALYZE_GROUP_CONVERSATION_FILTER)) {
1527         sep_entry->path = "/Analyze/Conversation Filter/";
1528         /*gtk_item_factory_create_item(main_menu_factory, sep_entry, NULL, 2);*/
1529     }
1530     if (merge_tap_menus_layered(node, REGISTER_TOOLS_GROUP_UNSORTED)) {
1531         /*gtk_item_factory_create_item(main_menu_factory, sep_entry, NULL, 2);*/
1532     }
1533
1534     g_free (sep_entry);
1535 }
1536
1537
1538
1539 /*
1540  * Enable/disable menu sensitivity.
1541  */
1542 static void
1543 set_menu_sensitivity(GtkItemFactory *ifactory, const gchar *path, gint val)
1544 {
1545     GSList *menu_list;
1546     GtkWidget *menu_item;
1547     gchar *dup;
1548     gchar *dest;
1549
1550
1551     /* the underscore character regularly confuses things, as it will prevent finding
1552      * the menu_item, so it has to be removed first */
1553     dup = g_strdup(path);
1554     dest = dup;
1555     while(*path) {
1556         if (*path != '_') {
1557             *dest = *path;
1558             dest++;
1559         }
1560         path++;
1561     }
1562     *dest = '\0';
1563
1564     if (ifactory == NULL) {
1565         /*
1566          * Do it for all pop-up menus.
1567          */
1568         for (menu_list = popup_menu_list; menu_list != NULL;
1569              menu_list = g_slist_next(menu_list))
1570             set_menu_sensitivity(menu_list->data, dup, val);
1571     } else {
1572         /*
1573          * Do it for that particular menu.
1574          */
1575         if ((menu_item = gtk_item_factory_get_widget(ifactory, dup)) != NULL) {
1576             if (GTK_IS_MENU(menu_item)) {
1577                 /*
1578                  * "dup" refers to a submenu; "gtk_item_factory_get_widget()"
1579                  * gets the menu, not the item that, when selected, pops up
1580                  * the submenu.
1581                  *
1582                  * We have to change the latter item's sensitivity, so that
1583                  * it shows up normally if sensitive and grayed-out if
1584                  * insensitive.
1585                  */
1586                 menu_item = gtk_menu_get_attach_widget(GTK_MENU(menu_item));
1587             }
1588             gtk_widget_set_sensitive(menu_item, val);
1589         } else{
1590             /* be sure this menu item *is* existing */
1591             g_assert_not_reached();
1592         }
1593     }
1594
1595     g_free(dup);
1596 }
1597
1598 static void
1599 set_menu_object_data_meat(GtkItemFactory *ifactory, const gchar *path, const gchar *key, gpointer data)
1600 {
1601     GtkWidget *menu = NULL;
1602
1603     if ((menu = gtk_item_factory_get_widget(ifactory, path)) != NULL)
1604         g_object_set_data(G_OBJECT(menu), key, data);
1605 }
1606
1607 void
1608 set_menu_object_data (const gchar *path, const gchar *key, gpointer data) {
1609     GSList *menu_list = popup_menu_list;
1610     gchar *shortpath = strrchr(path, '/');
1611
1612     set_menu_object_data_meat(main_menu_factory, path, key, data);
1613     while (menu_list != NULL) {
1614         set_menu_object_data_meat(menu_list->data, shortpath, key, data);
1615         set_menu_object_data_meat(menu_list->data, path, key, data);
1616         menu_list = g_slist_next(menu_list);
1617     }
1618 }
1619
1620
1621 /* Recently used capture files submenu:
1622  * Submenu containing the recently used capture files.
1623  * The capture filenames are always kept with the absolute path, to be independant
1624  * of the current path.
1625  * They are only stored inside the labels of the submenu (no separate list). */
1626
1627 #define MENU_RECENT_FILES_PATH "/File/Open Recent"
1628 #define MENU_RECENT_FILES_KEY "Recent File Name"
1629
1630
1631
1632 static void
1633 update_menu_recent_capture_file1(GtkWidget *widget, gpointer cnt) {
1634     gchar *widget_cf_name;
1635
1636     widget_cf_name = g_object_get_data(G_OBJECT(widget), MENU_RECENT_FILES_KEY);
1637
1638     /* if this menu item is a file, count it */
1639     if (widget_cf_name) {
1640         (*(guint *)cnt)++;
1641         main_welcome_add_recent_capture_files(widget_cf_name);
1642     }
1643 }
1644
1645
1646
1647 /* update the menu */
1648 static void
1649 update_menu_recent_capture_file(GtkWidget *submenu_recent_files) {
1650     guint cnt = 0;
1651
1652
1653     main_welcome_reset_recent_capture_files();
1654
1655     gtk_container_foreach(GTK_CONTAINER(submenu_recent_files),
1656                           update_menu_recent_capture_file1, &cnt);
1657
1658     /* make parent menu item sensitive only, if we have any valid files in the list */
1659     set_menu_sensitivity(main_menu_factory, MENU_RECENT_FILES_PATH, cnt);
1660 }
1661
1662
1663
1664 /* remove the capture filename from the "Recent Files" menu */
1665 static void
1666 remove_menu_recent_capture_filename(gchar *cf_name) {
1667     GtkWidget *submenu_recent_files;
1668     GList* child_list;
1669     GList* child_list_item;
1670     GtkWidget    *menu_item_child;
1671     const gchar *menu_item_cf_name;
1672     
1673
1674     /* get the submenu container item */
1675     submenu_recent_files = gtk_item_factory_get_widget(main_menu_factory, MENU_RECENT_FILES_PATH);
1676
1677     /* find the corresponding menu item to be removed */
1678     child_list = gtk_container_get_children(GTK_CONTAINER(submenu_recent_files));
1679     child_list_item = child_list;
1680     while(child_list_item) {
1681         menu_item_child = (GTK_BIN(child_list_item->data))->child;
1682         if (menu_item_child != NULL) { /* Note: there are two "extra" items on the end of the child_list: */
1683                                        /*  - a separator (with no menu_item_child and thus no text label) */
1684                                        /*  - a 2nd item with a menu_child with text label "Clear"         */
1685                                        /*       [See add_menu_recent_capture_file_absolute() ]            */
1686                                        /* 'if (menu_item_child != NULL)' skips the separator item;        */
1687                                        /* An absolute filename in cf_name will never match  "Clear".      */
1688             menu_item_cf_name = gtk_label_get_text(GTK_LABEL(menu_item_child));
1689             if(strcmp(menu_item_cf_name, cf_name) == 0) {
1690                 /* XXX: is this all we need to do, to free the menu item and its label?
1691                    The reference count of widget will go to 0, so it'll be freed;
1692                    will that free the label? */
1693                 gtk_container_remove(GTK_CONTAINER(submenu_recent_files), child_list_item->data);
1694             }
1695         }
1696         child_list_item = g_list_next(child_list_item);
1697     }
1698     g_list_free(child_list);
1699
1700     update_menu_recent_capture_file(submenu_recent_files);
1701 }
1702
1703
1704 /* remove the capture filename from the "Recent Files" menu */
1705 static void
1706 remove_menu_recent_capture_file(GtkWidget *widget, gpointer unused _U_) {
1707     GtkWidget *submenu_recent_files;
1708     gchar *widget_cf_name;
1709
1710
1711     widget_cf_name = g_object_get_data(G_OBJECT(widget), MENU_RECENT_FILES_KEY);
1712     g_free(widget_cf_name);
1713
1714     /* get the submenu container item */
1715     submenu_recent_files = gtk_item_factory_get_widget(main_menu_factory, MENU_RECENT_FILES_PATH);
1716
1717     /* XXX: is this all we need to do, to free the menu item and its label?
1718        The reference count of widget will go to 0, so it'll be freed;
1719        will that free the label? */
1720     gtk_container_remove(GTK_CONTAINER(submenu_recent_files), widget);
1721 }
1722
1723
1724 /* callback, if the user pushed the <Clear> menu item */
1725 static void
1726 clear_menu_recent_capture_file_cmd_cb(GtkWidget *w _U_, gpointer unused _U_) {
1727     GtkWidget *submenu_recent_files;
1728
1729
1730     submenu_recent_files = gtk_item_factory_get_widget(main_menu_factory, MENU_RECENT_FILES_PATH);
1731
1732     gtk_container_foreach(GTK_CONTAINER(submenu_recent_files),
1733                           remove_menu_recent_capture_file, NULL);
1734
1735     update_menu_recent_capture_file(submenu_recent_files);
1736 }
1737
1738
1739 /* Open a file by it's name
1740    (Beware: will not ask to close existing capture file!) */
1741 void
1742 menu_open_filename(gchar *cf_name)
1743 {
1744     GtkWidget *submenu_recent_files;
1745     int       err;
1746
1747     submenu_recent_files = gtk_item_factory_get_widget(main_menu_factory, MENU_RECENT_FILES_PATH);
1748
1749     /* open and read the capture file (this will close an existing file) */
1750     if (cf_open(&cfile, cf_name, FALSE, &err) == CF_OK) {
1751         cf_read(&cfile);
1752     } else {
1753         /* the capture file apparently no longer exists; remove menu item    */
1754         /* XXX: ask user to remove item, it's maybe only a temporary problem */
1755         remove_menu_recent_capture_filename(cf_name);
1756     }
1757
1758     update_menu_recent_capture_file(submenu_recent_files);
1759 }
1760
1761
1762 /* callback, if the user pushed a recent file submenu item */
1763 void
1764 menu_open_recent_file_cmd(GtkWidget *w)
1765 {
1766     GtkWidget   *submenu_recent_files;
1767     GtkWidget   *menu_item_child;
1768     const gchar *cf_name;
1769     int         err;
1770
1771     submenu_recent_files = gtk_item_factory_get_widget(main_menu_factory, MENU_RECENT_FILES_PATH);
1772
1773     /* get capture filename from the menu item label */
1774     menu_item_child = (GTK_BIN(w))->child;
1775     cf_name = gtk_label_get_text(GTK_LABEL(menu_item_child));
1776
1777     /* open and read the capture file (this will close an existing file) */
1778     if (cf_open(&cfile, cf_name, FALSE, &err) == CF_OK) {
1779         cf_read(&cfile);
1780     } else {
1781         /* the capture file apparently no longer exists; remove menu item    */
1782         /* XXX: ask user to remove item, it's maybe only a temporary problem */
1783         remove_menu_recent_capture_file(w, NULL);
1784     }
1785
1786     update_menu_recent_capture_file(submenu_recent_files);
1787 }
1788
1789 static void menu_open_recent_file_answered_cb(gpointer dialog _U_, gint btn, gpointer data)
1790 {
1791     switch(btn) {
1792     case(ESD_BTN_YES):
1793         /* save file first */
1794         file_save_as_cmd(after_save_open_recent_file, data);
1795         break;
1796     case(ESD_BTN_NO):
1797         cf_close(&cfile);
1798         menu_open_recent_file_cmd(data);
1799         break;
1800     case(ESD_BTN_CANCEL):
1801         break;
1802     default:
1803         g_assert_not_reached();
1804     }
1805 }
1806
1807 static void
1808 menu_open_recent_file_cmd_cb(GtkWidget *widget, gpointer data _U_) {
1809     gpointer  dialog;
1810
1811
1812     if((cfile.state != FILE_CLOSED) && !cfile.user_saved && prefs.gui_ask_unsaved) {
1813         /* user didn't saved his current file, ask him */
1814         dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_YES_NO_CANCEL,
1815                                "%sSave capture file before opening a new one?%s\n\n"
1816                                "If you open a new capture file without saving, your current capture data will be discarded.",
1817                                simple_dialog_primary_start(), simple_dialog_primary_end());
1818         simple_dialog_set_cb(dialog, menu_open_recent_file_answered_cb, widget);
1819     } else {
1820         /* unchanged file */
1821         menu_open_recent_file_cmd(widget);
1822     }
1823 }
1824
1825 /* add the capture filename (with an absolute path) to the "Recent Files" menu */
1826 static void
1827 add_menu_recent_capture_file_absolute(gchar *cf_name) {
1828     GtkWidget *submenu_recent_files;
1829     GList *menu_item_list;
1830     GList *li;
1831     gchar *widget_cf_name;
1832     gchar *normalized_cf_name;
1833     GtkWidget *menu_item;
1834     guint cnt;
1835
1836
1837
1838     normalized_cf_name = g_strdup(cf_name);
1839 #ifdef _WIN32
1840     /* replace all slashes by backslashes */
1841     g_strdelimit(normalized_cf_name, "/", '\\');
1842 #endif
1843
1844     /* get the submenu container item */
1845     submenu_recent_files = gtk_item_factory_get_widget(main_menu_factory, MENU_RECENT_FILES_PATH);
1846
1847     /* convert container to a GList */
1848     menu_item_list = gtk_container_get_children(GTK_CONTAINER(submenu_recent_files));
1849
1850     /* iterate through list items of menu_item_list,
1851      * removing special items, a maybe duplicate entry and every item above count_max */
1852     cnt = 1;
1853     for (li = g_list_first(menu_item_list); li; li = li->next, cnt++) {
1854         /* get capture filename */
1855         menu_item = GTK_WIDGET(li->data);
1856         widget_cf_name = g_object_get_data(G_OBJECT(menu_item), MENU_RECENT_FILES_KEY);
1857
1858         /* if this element string is one of our special items (seperator, ...) or
1859          * already in the list or
1860          * this element is above maximum count (too old), remove it */
1861         if (!widget_cf_name ||
1862 #ifdef _WIN32
1863             /* do a case insensitive compare on win32 */
1864             g_ascii_strncasecmp(widget_cf_name, normalized_cf_name, 1000) == 0 ||
1865 #else   /* _WIN32 */
1866             /* do a case sensitive compare on unix */
1867             strncmp(widget_cf_name, normalized_cf_name, 1000) == 0 ||
1868 #endif
1869             cnt >= prefs.gui_recent_files_count_max) {
1870             remove_menu_recent_capture_file(li->data, NULL);
1871             cnt--;
1872         }
1873     }
1874
1875     g_list_free(menu_item_list);
1876
1877     /* add new item at latest position */
1878     menu_item = gtk_menu_item_new_with_label(normalized_cf_name);
1879     g_object_set_data(G_OBJECT(menu_item), MENU_RECENT_FILES_KEY, normalized_cf_name);
1880     gtk_menu_shell_prepend (GTK_MENU_SHELL(submenu_recent_files), menu_item);
1881     g_signal_connect_swapped(GTK_OBJECT(menu_item), "activate",
1882                              G_CALLBACK(menu_open_recent_file_cmd_cb), (GtkObject *) menu_item);
1883     gtk_widget_show (menu_item);
1884
1885     /* add seperator at last position */
1886     menu_item = gtk_menu_item_new();
1887     gtk_menu_shell_append (GTK_MENU_SHELL(submenu_recent_files), menu_item);
1888     gtk_widget_show (menu_item);
1889
1890     /* add new "clear list" item at last position */
1891     menu_item = gtk_image_menu_item_new_from_stock(GTK_STOCK_CLEAR, NULL);
1892     gtk_menu_shell_append (GTK_MENU_SHELL(submenu_recent_files), menu_item);
1893     g_signal_connect_swapped(GTK_OBJECT(menu_item), "activate",
1894                              G_CALLBACK(clear_menu_recent_capture_file_cmd_cb), (GtkObject *) menu_item);
1895     gtk_widget_show (menu_item);
1896
1897     update_menu_recent_capture_file(submenu_recent_files);
1898 }
1899
1900
1901 /* add the capture filename to the "Recent Files" menu */
1902 /* (will change nothing, if this filename is already in the menu) */
1903 /*
1904  * XXX - We might want to call SHAddToRecentDocs under Windows 7:
1905  * http://stackoverflow.com/questions/437212/how-do-you-register-a-most-recently-used-list-with-windows-in-preparation-for-win
1906  */
1907 void
1908 add_menu_recent_capture_file(gchar *cf_name) {
1909     gchar *curr;
1910     gchar *absolute;
1911
1912
1913     /* if this filename is an absolute path, we can use it directly */
1914     if (g_path_is_absolute(cf_name)) {
1915         add_menu_recent_capture_file_absolute(cf_name);
1916         return;
1917     }
1918
1919     /* this filename is not an absolute path, prepend the current dir */
1920     curr = g_get_current_dir();
1921     absolute = g_strdup_printf("%s%s%s", curr, G_DIR_SEPARATOR_S, cf_name);
1922     add_menu_recent_capture_file_absolute(absolute);
1923     g_free(curr);
1924     g_free(absolute);
1925 }
1926
1927
1928 /* write all capture filenames of the menu to the user's recent file */
1929 void
1930 menu_recent_file_write_all(FILE *rf) {
1931     GtkWidget   *submenu_recent_files;
1932     GList       *children;
1933     GList       *child;
1934     gchar       *cf_name;
1935
1936
1937     submenu_recent_files = gtk_item_factory_get_widget(main_menu_factory, MENU_RECENT_FILES_PATH);
1938
1939     /* we have to iterate backwards through the children's list,
1940      * so we get the latest item last in the file.
1941      * (don't use gtk_container_foreach() here, it will return the wrong iteration order) */
1942     children = gtk_container_get_children(GTK_CONTAINER(submenu_recent_files));
1943     child = g_list_last(children);
1944     while(child != NULL) {
1945         /* get capture filename from the menu item label */
1946         cf_name = g_object_get_data(G_OBJECT(child->data), MENU_RECENT_FILES_KEY);
1947         if (cf_name) {
1948             if(u3_active())
1949                 fprintf (rf, RECENT_KEY_CAPTURE_FILE ": %s\n", u3_contract_device_path(cf_name));
1950             else
1951                 fprintf (rf, RECENT_KEY_CAPTURE_FILE ": %s\n", cf_name);
1952         }
1953
1954         child = g_list_previous(child);
1955     }
1956
1957     g_list_free(children);
1958 }
1959
1960
1961 static void
1962 show_hide_cb(GtkWidget *w, gpointer data _U_, gint action)
1963 {
1964
1965     /* save current setting in recent */
1966     switch(action) {
1967         case(SHOW_HIDE_MAIN_TOOLBAR):
1968         recent.main_toolbar_show = GTK_CHECK_MENU_ITEM(w)->active;
1969         break;
1970         case(SHOW_HIDE_FILTER_TOOLBAR):
1971         recent.filter_toolbar_show = GTK_CHECK_MENU_ITEM(w)->active;
1972         break;
1973 #ifdef HAVE_AIRPCAP
1974         case(SHOW_HIDE_AIRPCAP_TOOLBAR):
1975         recent.airpcap_toolbar_show = GTK_CHECK_MENU_ITEM(w)->active;
1976         break;
1977 #endif
1978         case(SHOW_HIDE_STATUSBAR):
1979         recent.statusbar_show = GTK_CHECK_MENU_ITEM(w)->active;
1980         break;
1981         case(SHOW_HIDE_PACKET_LIST):
1982         recent.packet_list_show = GTK_CHECK_MENU_ITEM(w)->active;
1983         break;
1984         case(SHOW_HIDE_TREE_VIEW):
1985         recent.tree_view_show = GTK_CHECK_MENU_ITEM(w)->active;
1986         break;
1987         case(SHOW_HIDE_BYTE_VIEW):
1988         recent.byte_view_show = GTK_CHECK_MENU_ITEM(w)->active;
1989         break;
1990         default:
1991             g_assert_not_reached();
1992     }
1993
1994     main_widgets_show_or_hide();
1995 }
1996
1997
1998 static void
1999 timestamp_format_cb(GtkWidget *w _U_, gpointer d _U_, gint action)
2000 {
2001     if (recent.gui_time_format != action) {
2002         timestamp_set_type(action);
2003         recent.gui_time_format = action;
2004         cf_change_time_formats(&cfile);
2005     }
2006 }
2007
2008
2009 static void
2010 timestamp_precision_cb(GtkWidget *w _U_, gpointer d _U_, gint action)
2011 {
2012     if (recent.gui_time_precision != action) {
2013         /* the actual precision will be set in cf_change_time_formats() below */
2014         if (action == TS_PREC_AUTO) {
2015             timestamp_set_precision(TS_PREC_AUTO_SEC);
2016         } else {
2017             timestamp_set_precision(action);
2018         }
2019         recent.gui_time_precision  = action;
2020         cf_change_time_formats(&cfile);
2021     }
2022 }
2023
2024
2025 void
2026 menu_name_resolution_changed(void)
2027 {
2028     GtkWidget *menu = NULL;
2029
2030     menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Name Resolution/Enable for MAC Layer");
2031     gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), g_resolv_flags & RESOLV_MAC);
2032
2033     menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Name Resolution/Enable for Network Layer");
2034     gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), g_resolv_flags & RESOLV_NETWORK);
2035
2036     menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Name Resolution/Enable for Transport Layer");
2037     gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), g_resolv_flags & RESOLV_TRANSPORT);
2038 }
2039
2040 static void
2041 name_resolution_cb(GtkWidget *w, gpointer d _U_, gint action)
2042 {
2043     if (GTK_CHECK_MENU_ITEM(w)->active) {
2044         g_resolv_flags |= action;
2045     } else {
2046         g_resolv_flags &= ~action;
2047     }
2048 }
2049
2050 #ifdef HAVE_LIBPCAP
2051 void
2052 menu_auto_scroll_live_changed(gboolean auto_scroll_live_in) {
2053     GtkWidget *menu;
2054
2055
2056     /* tell menu about it */
2057     menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Auto Scroll in Live Capture");
2058     if( ((gboolean) GTK_CHECK_MENU_ITEM(menu)->active) != auto_scroll_live_in) {
2059         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), auto_scroll_live_in);
2060     }
2061
2062     /* tell toolbar about it */
2063     toolbar_auto_scroll_live_changed(auto_scroll_live_in);
2064
2065     /* change auto scroll */
2066     if(auto_scroll_live_in != auto_scroll_live) {
2067         auto_scroll_live  = auto_scroll_live_in;
2068     }
2069 }
2070
2071 static void
2072 auto_scroll_live_cb(GtkWidget *w _U_, gpointer d _U_)
2073 {
2074     menu_auto_scroll_live_changed(GTK_CHECK_MENU_ITEM(w)->active);
2075 }
2076 #endif
2077
2078
2079 void
2080 menu_colorize_changed(gboolean packet_list_colorize) {
2081     GtkWidget *menu;
2082
2083
2084     /* tell menu about it */
2085     menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Colorize Packet List");
2086     if( ((gboolean) GTK_CHECK_MENU_ITEM(menu)->active) != packet_list_colorize) {
2087         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), packet_list_colorize);
2088     }
2089
2090     /* tell toolbar about it */
2091     toolbar_colorize_changed(packet_list_colorize);
2092
2093     /* change colorization */
2094     if(packet_list_colorize != recent.packet_list_colorize) {
2095         recent.packet_list_colorize = packet_list_colorize;
2096         color_filters_enable(packet_list_colorize);
2097         cf_colorize_packets(&cfile);
2098     }
2099 }
2100
2101 static void
2102 colorize_cb(GtkWidget *w, gpointer d _U_)
2103 {
2104     menu_colorize_changed(GTK_CHECK_MENU_ITEM(w)->active);
2105 }
2106
2107
2108 /* the recent file read has finished, update the menu corresponding */
2109 void
2110 menu_recent_read_finished(void) {
2111     GtkWidget *menu = NULL;
2112
2113     menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Main Toolbar");
2114     gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), recent.main_toolbar_show);
2115
2116     menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Filter Toolbar");
2117     gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), recent.filter_toolbar_show);
2118
2119 #ifdef HAVE_AIRPCAP
2120     menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Wireless Toolbar");
2121     gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), recent.airpcap_toolbar_show);
2122 #endif
2123
2124     menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Statusbar");
2125     gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), recent.statusbar_show);
2126
2127     menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Packet List");
2128     gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), recent.packet_list_show);
2129
2130     menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Packet Details");
2131     gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), recent.tree_view_show);
2132
2133     menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Packet Bytes");
2134     gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), recent.byte_view_show);
2135
2136     menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Colorize Packet List");
2137     gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), recent.packet_list_colorize);
2138
2139     menu_name_resolution_changed();
2140
2141 #ifdef HAVE_LIBPCAP
2142     menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Auto Scroll in Live Capture");
2143     gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), auto_scroll_live);
2144 #endif
2145
2146     main_widgets_rearrange();
2147
2148     /* don't change the time format, if we had a command line value */
2149     if (timestamp_get_type() != TS_NOT_SET) {
2150         recent.gui_time_format = timestamp_get_type();
2151     }
2152
2153     switch(recent.gui_time_format) {
2154     case(TS_ABSOLUTE_WITH_DATE):
2155         menu = gtk_item_factory_get_widget(main_menu_factory,
2156             "/View/Time Display Format/Date and Time of Day:   1970-01-01 01:02:03.123456");
2157         /* set_active will not trigger the callback when activating an active item! */
2158         recent.gui_time_format = -1;
2159         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), FALSE);
2160         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), TRUE);
2161         break;
2162     case(TS_ABSOLUTE):
2163         menu = gtk_item_factory_get_widget(main_menu_factory,
2164             "/View/Time Display Format/Time of Day:   01:02:03.123456");
2165         /* set_active will not trigger the callback when activating an active item! */
2166         recent.gui_time_format = -1;
2167         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), TRUE);
2168         break;
2169     case(TS_RELATIVE):
2170         menu = gtk_item_factory_get_widget(main_menu_factory,
2171             "/View/Time Display Format/Seconds Since Beginning of Capture:   123.123456");
2172         recent.gui_time_format = -1;
2173         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), TRUE);
2174         break;
2175     case(TS_DELTA):
2176         menu = gtk_item_factory_get_widget(main_menu_factory,
2177             "/View/Time Display Format/Seconds Since Previous Captured Packet:   1.123456");
2178         recent.gui_time_format = -1;
2179         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), TRUE);
2180         break;
2181     case(TS_DELTA_DIS):
2182         menu = gtk_item_factory_get_widget(main_menu_factory,
2183             "/View/Time Display Format/Seconds Since Previous Displayed Packet:   1.123456");
2184         recent.gui_time_format = -1;
2185         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), TRUE);
2186         break;
2187     case(TS_EPOCH):
2188         menu = gtk_item_factory_get_widget(main_menu_factory,
2189             "/View/Time Display Format/Seconds Since Epoch (1970-01-01):   1234567890.123456");
2190         recent.gui_time_format = -1;
2191         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), TRUE);
2192         break;
2193     default:
2194         g_assert_not_reached();
2195     }
2196
2197     switch(recent.gui_time_precision) {
2198     case(TS_PREC_AUTO):
2199         menu = gtk_item_factory_get_widget(main_menu_factory,
2200             "/View/Time Display Format/Automatic (File Format Precision)");
2201         /* set_active will not trigger the callback when activating an active item! */
2202         recent.gui_time_precision = -1;
2203         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), FALSE);
2204         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), TRUE);
2205         break;
2206     case(TS_PREC_FIXED_SEC):
2207         menu = gtk_item_factory_get_widget(main_menu_factory,
2208             "/View/Time Display Format/Seconds:   0");
2209         recent.gui_time_precision = -1;
2210         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), TRUE);
2211         break;
2212     case(TS_PREC_FIXED_DSEC):
2213         menu = gtk_item_factory_get_widget(main_menu_factory,
2214             "/View/Time Display Format/Deciseconds:   0.1");
2215         recent.gui_time_precision = -1;
2216         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), TRUE);
2217         break;
2218     case(TS_PREC_FIXED_CSEC):
2219         menu = gtk_item_factory_get_widget(main_menu_factory,
2220             "/View/Time Display Format/Centiseconds:   0.12");
2221         recent.gui_time_precision = -1;
2222         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), TRUE);
2223         break;
2224     case(TS_PREC_FIXED_MSEC):
2225         menu = gtk_item_factory_get_widget(main_menu_factory,
2226             "/View/Time Display Format/Milliseconds:   0.123");
2227         recent.gui_time_precision = -1;
2228         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), TRUE);
2229         break;
2230     case(TS_PREC_FIXED_USEC):
2231         menu = gtk_item_factory_get_widget(main_menu_factory,
2232             "/View/Time Display Format/Microseconds:   0.123456");
2233         recent.gui_time_precision = -1;
2234         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), TRUE);
2235         break;
2236     case(TS_PREC_FIXED_NSEC):
2237         menu = gtk_item_factory_get_widget(main_menu_factory,
2238             "/View/Time Display Format/Nanoseconds:   0.123456789");
2239         recent.gui_time_precision = -1;
2240         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), TRUE);
2241         break;
2242     default:
2243         g_assert_not_reached();
2244     }
2245
2246     menu_colorize_changed(recent.packet_list_colorize);
2247 }
2248
2249
2250 gint
2251 popup_menu_handler(GtkWidget *widget, GdkEvent *event, gpointer data)
2252 {
2253     GtkWidget *menu = (GtkWidget *)data;
2254     GdkEventButton *event_button = NULL;
2255     gint row, column;
2256
2257     if(widget == NULL || event == NULL || data == NULL) {
2258         return FALSE;
2259     }
2260
2261     /*
2262      * If we ever want to make the menu differ based on what row
2263      * and/or column we're above, we'd use "eth_clist_get_selection_info()"
2264      * to find the row and column number for the coordinates; a CTree is,
2265      * I guess, like a CList with one column(?) and the expander widget
2266      * as a pixmap.
2267      */
2268     /* Check if we are on packet_list object */
2269     if (widget == g_object_get_data(G_OBJECT(popup_menu_object), E_MPACKET_LIST_KEY) &&
2270         ((GdkEventButton *)event)->button != 1) {
2271         if (packet_list_get_event_row_column(widget, (GdkEventButton *)event,
2272                                              &row, &column)) {
2273             g_object_set_data(G_OBJECT(popup_menu_object), E_MPACKET_LIST_ROW_KEY,
2274                             GINT_TO_POINTER(row));
2275             g_object_set_data(G_OBJECT(popup_menu_object), E_MPACKET_LIST_COL_KEY,
2276                             GINT_TO_POINTER(column));
2277             packet_list_set_selected_row(row);
2278         }
2279     }
2280
2281     /* Check if we are on tree_view object */
2282     if (widget == tree_view) {
2283         tree_view_select(widget, (GdkEventButton *) event);
2284     }
2285
2286     /* Check if we are on byte_view object */
2287     if(widget == get_notebook_bv_ptr(byte_nb_ptr)) {
2288         byte_view_select(widget, (GdkEventButton *) event);
2289     }
2290
2291     /* context menu handler */
2292     if(event->type == GDK_BUTTON_PRESS) {
2293         event_button = (GdkEventButton *) event;
2294
2295         /* To qoute the "Gdk Event Structures" doc:
2296          * "Normally button 1 is the left mouse button, 2 is the middle button, and 3 is the right button" */
2297         if(event_button->button == 3) {
2298             /* No popup window in the byte view */
2299             if(widget != get_notebook_bv_ptr(byte_nb_ptr)) {
2300                 gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL,
2301                                event_button->button,
2302                                event_button->time);
2303             }
2304             g_signal_stop_emission_by_name(widget, "button_press_event");
2305             return TRUE;
2306         }
2307     }
2308     /* GDK_2BUTTON_PRESS is a doubleclick -> expand/collapse tree row */
2309     /* GTK version 1 seems to be doing this automatically */
2310     if (widget == tree_view && event->type == GDK_2BUTTON_PRESS) {
2311         GtkTreePath      *path;
2312
2313         if (gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(widget),
2314                                           (gint) (((GdkEventButton *)event)->x),
2315                                           (gint) (((GdkEventButton *)event)->y),
2316                                           &path, NULL, NULL, NULL))
2317         {
2318             if (gtk_tree_view_row_expanded(GTK_TREE_VIEW(widget), path))
2319                 gtk_tree_view_collapse_row(GTK_TREE_VIEW(widget), path);
2320             else
2321                 gtk_tree_view_expand_row(GTK_TREE_VIEW(widget), path,
2322                                          FALSE);
2323             gtk_tree_path_free(path);
2324         }
2325     }
2326     return FALSE;
2327 }
2328
2329 /* Enable or disable menu items based on whether you have a capture file
2330    you've finished reading and, if you have one, whether it's been saved
2331    and whether it could be saved except by copying the raw packet data. */
2332 void
2333 set_menus_for_capture_file(capture_file *cf)
2334 {
2335     if (cf == NULL) {
2336         /* We have no capture file */
2337         set_menu_sensitivity(main_menu_factory, "/File/Merge...", FALSE);
2338         set_menu_sensitivity(main_menu_factory, "/File/Close", FALSE);
2339         set_menu_sensitivity(main_menu_factory, "/File/Save", FALSE);
2340         set_menu_sensitivity(main_menu_factory, "/File/Save As...", FALSE);
2341         set_menu_sensitivity(main_menu_factory, "/File/Export", FALSE);
2342         set_menu_sensitivity(main_menu_factory, "/View/Reload", FALSE);
2343         set_toolbar_for_capture_file(FALSE);
2344         set_toolbar_for_unsaved_capture_file(FALSE);
2345     } else {
2346         set_menu_sensitivity(main_menu_factory, "/File/Merge...", TRUE);
2347         set_menu_sensitivity(main_menu_factory, "/File/Close", TRUE);
2348         set_menu_sensitivity(main_menu_factory, "/File/Save", !cf->user_saved);
2349         /*
2350          * "Save As..." works only if we can write the file out in at least
2351          * one format (so we can save the whole file or just a subset) or
2352          * if we have an unsaved capture (so writing the whole file out
2353          * with a raw data copy makes sense).
2354          */
2355         set_menu_sensitivity(main_menu_factory, "/File/Save As...",
2356                              cf_can_save_as(cf) || !cf->user_saved);
2357         set_menu_sensitivity(main_menu_factory, "/File/Export", TRUE);
2358         set_menu_sensitivity(main_menu_factory, "/View/Reload", TRUE);
2359         set_toolbar_for_unsaved_capture_file(!cf->user_saved);
2360         set_toolbar_for_capture_file(TRUE);
2361     }
2362 }
2363
2364 /* Enable or disable menu items based on whether there's a capture in
2365    progress. */
2366 void
2367 set_menus_for_capture_in_progress(gboolean capture_in_progress)
2368 {
2369     set_menu_sensitivity(main_menu_factory, "/File/Open...",
2370                          !capture_in_progress);
2371     set_menu_sensitivity(main_menu_factory, "/File/Open Recent",
2372                          !capture_in_progress);
2373     set_menu_sensitivity(main_menu_factory, "/File/Export",
2374                          capture_in_progress);
2375 #ifdef HAVE_LIBPCAP
2376     set_menu_sensitivity(main_menu_factory, "/Capture/Options...",
2377                          !capture_in_progress);
2378     set_menu_sensitivity(main_menu_factory, "/Capture/Start",
2379                          !capture_in_progress);
2380     set_menu_sensitivity(main_menu_factory, "/Capture/Stop",
2381                          capture_in_progress);
2382     set_menu_sensitivity(main_menu_factory, "/Capture/Restart",
2383                          capture_in_progress);
2384     set_toolbar_for_capture_in_progress(capture_in_progress);
2385
2386     set_capture_if_dialog_for_capture_in_progress(capture_in_progress);
2387 #endif /* HAVE_LIBPCAP */
2388 }
2389
2390 /* Enable or disable menu items based on whether you have some captured
2391    packets. */
2392 static gboolean
2393 walk_menu_tree_for_captured_packets(GList *node,
2394     gboolean have_captured_packets)
2395 {
2396     gboolean    is_enabled;
2397     GList       *child;
2398     menu_item_t *node_data = node->data;
2399
2400     /*
2401      * Is this a leaf node or an interior node?
2402      */
2403     if (node_data->children == NULL) {
2404         /*
2405          * It's a leaf node.
2406          *
2407          * If it has no "selected_packet_enabled()" or
2408          * "selected_tree_row_enabled()" routines, we enable
2409          * it.  This allows tap windows to be popped up even
2410          * if you have no capture file; this is done to let
2411          * the user pop up multiple tap windows before reading
2412          * in a capture file, so that they can be processed in
2413          * parallel while the capture file is being read rather
2414          * than one at at time as you pop up the windows, and to
2415          * let the user pop up tap windows before starting an
2416          * "Update list of packets in real time" capture, so that
2417          * the statistics can be displayed while the capture is
2418          * in progress.
2419          *
2420          * If it has either of those routines, we disable it for
2421          * now - as long as, when a capture is first available,
2422          * we don't get called after a packet or tree row is
2423          * selected, that's OK.
2424          * XXX - that should be done better.
2425          */
2426         if (node_data->selected_packet_enabled == NULL &&
2427             node_data->selected_tree_row_enabled == NULL)
2428             node_data->enabled = TRUE;
2429         else
2430             node_data->enabled = FALSE;
2431     } else {
2432         /*
2433          * It's an interior node; call
2434          * "walk_menu_tree_for_captured_packets()" on all its
2435          * children and, if any of them are enabled, enable
2436          * this node, otherwise disable it.
2437          *
2438          * XXX - should we just leave all interior nodes enabled?
2439          * Which is a better UI choice?
2440          */
2441         is_enabled = FALSE;
2442         for (child = node_data->children; child != NULL; child =
2443                  child->next) {
2444             if (walk_menu_tree_for_captured_packets(child,
2445                                                     have_captured_packets))
2446                 is_enabled = TRUE;
2447         }
2448         node_data->enabled = is_enabled;
2449     }
2450
2451     /*
2452      * The root node doesn't correspond to a menu tree item; it
2453      * has a null name pointer.
2454      */
2455     if (node_data->name != NULL) {
2456         set_menu_sensitivity(main_menu_factory, node_data->name,
2457                              node_data->enabled);
2458     }
2459     return node_data->enabled;
2460 }
2461
2462 void
2463 set_menus_for_captured_packets(gboolean have_captured_packets)
2464 {
2465     set_menu_sensitivity(main_menu_factory, "/File/Print...",
2466                          have_captured_packets);
2467     set_menu_sensitivity(packet_list_menu_factory, "/Print...",
2468                          have_captured_packets);
2469     set_menu_sensitivity(main_menu_factory, "/Edit/Find Packet...",
2470                          have_captured_packets);
2471     set_menu_sensitivity(main_menu_factory, "/Edit/Find Next",
2472                          have_captured_packets);
2473     set_menu_sensitivity(main_menu_factory, "/Edit/Find Previous",
2474                          have_captured_packets);
2475     set_menu_sensitivity(main_menu_factory, "/View/Zoom In",
2476                          have_captured_packets);
2477     set_menu_sensitivity(main_menu_factory, "/View/Zoom Out",
2478                          have_captured_packets);
2479     set_menu_sensitivity(main_menu_factory, "/View/Normal Size",
2480                          have_captured_packets);
2481     set_menu_sensitivity(main_menu_factory, "/Go/Go to Packet...",
2482                          have_captured_packets);
2483     set_menu_sensitivity(main_menu_factory, "/Go/Previous Packet",
2484                          have_captured_packets);
2485     set_menu_sensitivity(main_menu_factory, "/Go/Next Packet",
2486                          have_captured_packets);
2487     set_menu_sensitivity(main_menu_factory, "/Go/First Packet",
2488                          have_captured_packets);
2489     set_menu_sensitivity(main_menu_factory, "/Go/Last Packet",
2490                          have_captured_packets);
2491     set_menu_sensitivity(main_menu_factory, "/Statistics/Summary",
2492                          have_captured_packets);
2493     set_menu_sensitivity(main_menu_factory, "/Statistics/Protocol Hierarchy",
2494                          have_captured_packets);
2495
2496     walk_menu_tree_for_captured_packets(tap_menu_tree_root,
2497                                         have_captured_packets);
2498     set_toolbar_for_captured_packets(have_captured_packets);
2499 }
2500
2501 /* Enable or disable menu items based on whether a packet is selected and,
2502    if so, on the properties of the packet. */
2503 static gboolean
2504 walk_menu_tree_for_selected_packet(GList *node, frame_data *fd,
2505     epan_dissect_t *edt)
2506 {
2507     gboolean is_enabled;
2508     GList *child;
2509     menu_item_t *node_data = node->data;
2510
2511     /*
2512      * Is this a leaf node or an interior node?
2513      */
2514     if (node_data->children == NULL) {
2515         /*
2516          * It's a leaf node.
2517          *
2518          * If it has no "selected_packet_enabled()" routine,
2519          * leave its enabled/disabled status alone - it
2520          * doesn't depend on whether we have a packet selected
2521          * or not or on the selected packet.
2522          *
2523          * If it has a "selected_packet_enabled()" routine,
2524          * call it and set the item's enabled/disabled status
2525          * based on its return value.
2526          */
2527         if (node_data->selected_packet_enabled != NULL)
2528             node_data->enabled = node_data->selected_packet_enabled(fd, edt, node_data->callback_data);
2529     } else {
2530         /*
2531          * It's an interior node; call
2532          * "walk_menu_tree_for_selected_packet()" on all its
2533          * children and, if any of them are enabled, enable
2534          * this node, otherwise disable it.
2535          *
2536          * XXX - should we just leave all interior nodes enabled?
2537          * Which is a better UI choice?
2538          */
2539         is_enabled = FALSE;
2540         for (child = node_data->children; child != NULL; child =
2541                  child->next) {
2542             if (walk_menu_tree_for_selected_packet(child, fd, edt))
2543                 is_enabled = TRUE;
2544         }
2545         node_data->enabled = is_enabled;
2546     }
2547
2548     /*
2549      * The root node doesn't correspond to a menu tree item; it
2550      * has a null name pointer.
2551      */
2552     if (node_data->name != NULL) {
2553         set_menu_sensitivity(main_menu_factory, node_data->name,
2554                              node_data->enabled);
2555     }
2556     return node_data->enabled;
2557 }
2558
2559 gboolean
2560 packet_is_ssl(epan_dissect_t* edt)
2561 {
2562     GPtrArray* array;
2563     int ssl_id;
2564     gboolean is_ssl;
2565
2566     if (!edt || !edt->tree)
2567         return FALSE;
2568     ssl_id = proto_get_id_by_filter_name("ssl");
2569     if (ssl_id < 0)
2570         return FALSE;
2571     array = proto_find_finfo(edt->tree, ssl_id);
2572     is_ssl = (array->len > 0) ? TRUE : FALSE;
2573     g_ptr_array_free(array, FALSE);
2574     return is_ssl;
2575 }
2576
2577 void
2578 set_menus_for_selected_packet(capture_file *cf)
2579 {
2580     gboolean is_ssl = packet_is_ssl(cf->edt);
2581     set_menu_sensitivity(main_menu_factory, "/Edit/Mark Packet (toggle)",
2582                          cf->current_frame != NULL);
2583     set_menu_sensitivity(packet_list_menu_factory, "/Mark Packet (toggle)",
2584                          cf->current_frame != NULL);
2585     set_menu_sensitivity(main_menu_factory, "/Edit/Find Next Mark",
2586                          cf->current_frame != NULL);
2587     set_menu_sensitivity(main_menu_factory, "/Edit/Find Previous Mark",
2588                          cf->current_frame != NULL);
2589     set_menu_sensitivity(main_menu_factory, "/Edit/Mark All Packets",
2590                          cf->current_frame != NULL);
2591     set_menu_sensitivity(main_menu_factory, "/Edit/Unmark All Packets",
2592                          cf->current_frame != NULL);
2593     set_menu_sensitivity(main_menu_factory, "/Edit/Set Time Reference (toggle)",
2594                          cf->current_frame != NULL);
2595     set_menu_sensitivity(packet_list_menu_factory, "/Set Time Reference (toggle)",
2596                          cf->current_frame != NULL);
2597     set_menu_sensitivity(main_menu_factory, "/Edit/Find Next Reference",
2598                          cf->current_frame != NULL);
2599     set_menu_sensitivity(main_menu_factory, "/Edit/Find Previous Reference",
2600                          cf->current_frame != NULL);
2601     set_menu_sensitivity(main_menu_factory, "/View/Resize All Columns",
2602                          cf->current_frame != NULL);
2603     set_menu_sensitivity(main_menu_factory, "/View/Collapse All",
2604                          cf->current_frame != NULL);
2605     set_menu_sensitivity(tree_view_menu_factory, "/Collapse All",
2606                          cf->current_frame != NULL);
2607     set_menu_sensitivity(main_menu_factory, "/View/Expand All",
2608                          cf->current_frame != NULL);
2609     set_menu_sensitivity(tree_view_menu_factory, "/Expand All",
2610                          cf->current_frame != NULL);
2611     set_menu_sensitivity(main_menu_factory, "/View/Colorize Conversation",
2612                          cf->current_frame != NULL);
2613     set_menu_sensitivity(main_menu_factory, "/View/Reset Coloring 1-10",
2614                          tmp_color_filters_used());
2615     set_menu_sensitivity(main_menu_factory, "/View/Show Packet in New Window",
2616                          cf->current_frame != NULL);
2617     set_menu_sensitivity(packet_list_menu_factory, "/Show Packet in New Window",
2618                          cf->current_frame != NULL);
2619     set_menu_sensitivity(packet_list_menu_factory, "/SCTP",
2620                          cf->current_frame != NULL ? (cf->edt->pi.ipproto == IP_PROTO_SCTP) : FALSE);
2621     set_menu_sensitivity(main_menu_factory, "/Analyze/Follow TCP Stream",
2622                          cf->current_frame != NULL ? (cf->edt->pi.ipproto == IP_PROTO_TCP) : FALSE);
2623     set_menu_sensitivity(packet_list_menu_factory, "/Follow TCP Stream",
2624                          cf->current_frame != NULL ? (cf->edt->pi.ipproto == IP_PROTO_TCP) : FALSE);
2625     set_menu_sensitivity(tree_view_menu_factory, "/Follow TCP Stream",
2626                          cf->current_frame != NULL ? (cf->edt->pi.ipproto == IP_PROTO_TCP) : FALSE);
2627     set_menu_sensitivity(main_menu_factory, "/Analyze/Follow UDP Stream",
2628                          cf->current_frame != NULL ? (cf->edt->pi.ipproto == IP_PROTO_UDP) : FALSE);
2629     set_menu_sensitivity(packet_list_menu_factory, "/Follow UDP Stream",
2630                          cf->current_frame != NULL ? (cf->edt->pi.ipproto == IP_PROTO_UDP) : FALSE);
2631     set_menu_sensitivity(tree_view_menu_factory, "/Follow UDP Stream",
2632                          cf->current_frame != NULL ? (cf->edt->pi.ipproto == IP_PROTO_UDP) : FALSE);
2633     set_menu_sensitivity(main_menu_factory, "/Analyze/Follow SSL Stream",
2634                          cf->current_frame != NULL ? is_ssl : FALSE);
2635     set_menu_sensitivity(packet_list_menu_factory, "/Follow SSL Stream",
2636                          cf->current_frame != NULL ? is_ssl : FALSE);
2637     set_menu_sensitivity(tree_view_menu_factory, "/Follow SSL Stream",
2638                          cf->current_frame != NULL ? is_ssl : FALSE);
2639     set_menu_sensitivity(packet_list_menu_factory, "/Conversation Filter",
2640                          cf->current_frame != NULL);
2641     set_menu_sensitivity(packet_list_menu_factory, "/Conversation Filter/Ethernet",
2642                          cf->current_frame != NULL ? (cf->edt->pi.dl_src.type == AT_ETHER) : FALSE);
2643     set_menu_sensitivity(packet_list_menu_factory, "/Conversation Filter/IP",
2644                          cf->current_frame != NULL ? ((cf->edt->pi.ethertype == ETHERTYPE_IP)||(cf->edt->pi.ethertype == ETHERTYPE_IPv6)) : FALSE);
2645     set_menu_sensitivity(packet_list_menu_factory, "/Conversation Filter/TCP",
2646                          cf->current_frame != NULL ? (cf->edt->pi.ipproto == IP_PROTO_TCP) : FALSE);
2647     set_menu_sensitivity(packet_list_menu_factory, "/Conversation Filter/UDP",
2648                          cf->current_frame != NULL ? (cf->edt->pi.ipproto == IP_PROTO_UDP) : FALSE);
2649     set_menu_sensitivity(packet_list_menu_factory, "/Conversation Filter/PN-CBA Server",
2650                          cf->current_frame != NULL ? (cf->edt->pi.profinet_type != 0 && cf->edt->pi.profinet_type < 10) : FALSE);
2651     set_menu_sensitivity(packet_list_menu_factory, "/Colorize Conversation",
2652                          cf->current_frame != NULL);
2653     set_menu_sensitivity(packet_list_menu_factory, "/Colorize Conversation/Ethernet",
2654                          cf->current_frame != NULL ? (cf->edt->pi.dl_src.type == AT_ETHER) : FALSE);
2655     set_menu_sensitivity(packet_list_menu_factory, "/Colorize Conversation/IP",
2656                          cf->current_frame != NULL ? ((cf->edt->pi.ethertype == ETHERTYPE_IP)||(cf->edt->pi.ethertype == ETHERTYPE_IPv6)) : FALSE);
2657     set_menu_sensitivity(packet_list_menu_factory, "/Colorize Conversation/TCP",
2658                          cf->current_frame != NULL ? (cf->edt->pi.ipproto == IP_PROTO_TCP) : FALSE);
2659     set_menu_sensitivity(packet_list_menu_factory, "/Colorize Conversation/UDP",
2660                          cf->current_frame != NULL ? (cf->edt->pi.ipproto == IP_PROTO_UDP) : FALSE);
2661     set_menu_sensitivity(packet_list_menu_factory, "/Colorize Conversation/PN-CBA Server",
2662                          cf->current_frame != NULL ? (cf->edt->pi.profinet_type != 0 && cf->edt->pi.profinet_type < 10) : FALSE);
2663     set_menu_sensitivity(main_menu_factory, "/Analyze/Decode As...",
2664                          cf->current_frame != NULL && decode_as_ok());
2665     set_menu_sensitivity(packet_list_menu_factory, "/Decode As...",
2666                          cf->current_frame != NULL && decode_as_ok());
2667     set_menu_sensitivity(tree_view_menu_factory, "/Decode As...",
2668                          cf->current_frame != NULL && decode_as_ok());
2669     set_menu_sensitivity(main_menu_factory, "/View/Name Resolution/Resolve Name",
2670                          cf->current_frame != NULL && (g_resolv_flags & RESOLV_ALL_ADDRS) != RESOLV_ALL_ADDRS);
2671     set_menu_sensitivity(tree_view_menu_factory, "/Resolve Name",
2672                          cf->current_frame != NULL && (g_resolv_flags & RESOLV_ALL_ADDRS) != RESOLV_ALL_ADDRS);
2673     set_menu_sensitivity(packet_list_menu_factory, "/Copy",
2674                          cf->current_frame != NULL);
2675     set_menu_sensitivity(packet_list_menu_factory, "/Apply as Filter",
2676                          cf->current_frame != NULL);
2677     set_menu_sensitivity(packet_list_menu_factory, "/Prepare a Filter",
2678                          cf->current_frame != NULL);
2679     set_menu_sensitivity(main_menu_factory, "/Tools/Firewall ACL Rules",
2680                          cf->current_frame != NULL);
2681
2682     walk_menu_tree_for_selected_packet(tap_menu_tree_root, cf->current_frame,
2683                                        cf->edt);
2684 }
2685
2686 /* Enable or disable menu items based on whether a tree row is selected
2687    and, if so, on the properties of the tree row. */
2688 static gboolean
2689 walk_menu_tree_for_selected_tree_row(GList *node, field_info *fi)
2690 {
2691     gboolean is_enabled;
2692     GList *child;
2693     menu_item_t *node_data = node->data;
2694
2695     /*
2696      * Is this a leaf node or an interior node?
2697      */
2698     if (node_data->children == NULL) {
2699         /*
2700          * It's a leaf node.
2701          *
2702          * If it has no "selected_tree_row_enabled()" routine,
2703          * leave its enabled/disabled status alone - it
2704          * doesn't depend on whether we have a tree row selected
2705          * or not or on the selected tree row.
2706          *
2707          * If it has a "selected_tree_row_enabled()" routine,
2708          * call it and set the item's enabled/disabled status
2709          * based on its return value.
2710          */
2711         if (node_data->selected_tree_row_enabled != NULL)
2712             node_data->enabled = node_data->selected_tree_row_enabled(fi, node_data->callback_data);
2713     } else {
2714         /*
2715          * It's an interior node; call
2716          * "walk_menu_tree_for_selected_tree_row()" on all its
2717          * children and, if any of them are enabled, enable
2718          * this node, otherwise disable it.
2719          *
2720          * XXX - should we just leave all interior nodes enabled?
2721          * Which is a better UI choice?
2722          */
2723         is_enabled = FALSE;
2724         for (child = node_data->children; child != NULL; child =
2725                  child->next) {
2726             if (walk_menu_tree_for_selected_tree_row(child, fi))
2727                 is_enabled = TRUE;
2728         }
2729         node_data->enabled = is_enabled;
2730     }
2731
2732     /*
2733      * The root node doesn't correspond to a menu tree item; it
2734      * has a null name pointer.
2735      */
2736     if (node_data->name != NULL) {
2737         set_menu_sensitivity(main_menu_factory, node_data->name,
2738                              node_data->enabled);
2739     }
2740     return node_data->enabled;
2741 }
2742
2743 static void
2744 menu_prefs_toggle_bool (GtkWidget *w, gpointer data)
2745 {
2746     gboolean *value = data;
2747     module_t *module = g_object_get_data (G_OBJECT(w), "module");
2748
2749     module->prefs_changed = TRUE;
2750     *value = !(*value);
2751
2752     prefs_apply (module);
2753     if (!prefs.gui_use_pref_save) {
2754         prefs_main_write();
2755     }
2756     redissect_packets();
2757 }
2758
2759 static void
2760 menu_prefs_change_enum (GtkWidget *w, gpointer data)
2761 {
2762     gint *value = data;
2763     module_t *module = g_object_get_data (G_OBJECT(w), "module");
2764     gint new_value = GPOINTER_TO_INT(g_object_get_data (G_OBJECT(w), "enumval"));
2765
2766     if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM(w)))
2767         return;
2768
2769     if (*value != new_value) {
2770         module->prefs_changed = TRUE;
2771         *value = new_value;
2772
2773         prefs_apply (module);
2774         if (!prefs.gui_use_pref_save) {
2775             prefs_main_write();
2776         }
2777         redissect_packets();
2778     }
2779 }
2780
2781 void
2782 menu_prefs_reset(void)
2783 {
2784         g_free (g_object_get_data(G_OBJECT(tree_view_menu_factory), "menu_abbrev"));
2785         g_object_set_data(G_OBJECT(tree_view_menu_factory), "menu_abbrev", NULL);
2786 }
2787
2788 static void
2789 menu_prefs_change_ok (GtkWidget *w, gpointer parent_w)
2790 {
2791     GtkWidget *entry = g_object_get_data (G_OBJECT(w), "entry");
2792     module_t *module = g_object_get_data (G_OBJECT(w), "module");
2793     pref_t *pref = g_object_get_data (G_OBJECT(w), "pref");
2794     const gchar *new_value =  gtk_entry_get_text(GTK_ENTRY(entry));
2795     range_t *newrange;
2796     gchar *p;
2797     guint uval;
2798
2799     switch (pref->type) {
2800     case PREF_UINT:
2801         uval = strtoul(new_value, &p, pref->info.base);
2802         if (p == new_value || *p != '\0') {
2803             simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2804                           "The value \"%s\" isn't a valid number.",
2805                           new_value);
2806             return;
2807         }
2808         if (*pref->varp.uint != uval) {
2809             module->prefs_changed = TRUE;
2810             *pref->varp.uint = uval;
2811         }
2812         break;
2813     case PREF_STRING:
2814         if (strcmp (*pref->varp.string, new_value) != 0) {
2815             module->prefs_changed = TRUE;
2816             g_free((void*)*pref->varp.string);
2817             *pref->varp.string = g_strdup(new_value);
2818         }
2819         break;
2820     case PREF_RANGE:
2821         if (range_convert_str(&newrange, new_value, pref->info.max_value) != CVT_NO_ERROR) {
2822             simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2823                           "The value \"%s\" isn't a valid range.",
2824                           new_value);
2825             return;
2826         }
2827         if (!ranges_are_equal(*pref->varp.range, newrange)) {
2828             module->prefs_changed = TRUE;
2829             g_free(*pref->varp.range);
2830             *pref->varp.range = newrange;
2831         } else {
2832             g_free (newrange);
2833         }
2834         break;
2835     default:
2836         g_assert_not_reached();
2837         break;
2838     }
2839
2840     if (module->prefs_changed) {
2841         /* Ensure we reload the sub menu */
2842         menu_prefs_reset();
2843         prefs_apply (module);
2844         if (!prefs.gui_use_pref_save) {
2845             prefs_main_write();
2846         }
2847         redissect_packets();
2848     }
2849
2850     window_destroy(GTK_WIDGET(parent_w));
2851 }
2852
2853 static void
2854 menu_prefs_change_cancel (GtkWidget *w _U_, gpointer parent_w)
2855 {
2856     window_destroy(GTK_WIDGET(parent_w));
2857 }
2858
2859 static void 
2860 menu_prefs_edit_dlg (GtkWidget *w, gpointer data)
2861 {
2862     pref_t *pref = data;
2863     module_t *module = g_object_get_data (G_OBJECT(w), "module");
2864     gchar *value = NULL;
2865
2866     GtkWidget *win, *main_tb, *main_vb, *bbox, *cancel_bt, *ok_bt;
2867     GtkWidget *entry, *label;
2868     GtkTooltips *tooltips;
2869
2870     switch (pref->type) {
2871     case PREF_UINT:
2872         switch (pref->info.base) {
2873         case 8:
2874             value = g_strdup_printf("%o", *pref->varp.uint);
2875             break;
2876         case 10:
2877             value = g_strdup_printf("%u", *pref->varp.uint);
2878             break;
2879         case 16:
2880             value = g_strdup_printf("%x", *pref->varp.uint);
2881             break;
2882         default:
2883             g_assert_not_reached();
2884             break;
2885         }
2886         break;
2887     case PREF_STRING:
2888         value = g_strdup(*pref->varp.string);
2889         break;
2890     case PREF_RANGE:
2891         value = g_strdup(range_convert_range (*pref->varp.range));
2892         break;
2893     default:
2894         g_assert_not_reached();
2895         break;
2896     }
2897
2898     tooltips = gtk_tooltips_new();
2899
2900     win = dlg_window_new(module->description);
2901
2902     gtk_window_set_resizable(GTK_WINDOW(win),FALSE);
2903     gtk_window_resize(GTK_WINDOW(win), 400, 100);
2904
2905     main_vb = gtk_vbox_new(FALSE, 5);
2906     gtk_container_add(GTK_CONTAINER(win), main_vb);
2907     gtk_container_set_border_width(GTK_CONTAINER(main_vb), 6);
2908
2909     main_tb = gtk_table_new(2, 2, FALSE);
2910     gtk_box_pack_start(GTK_BOX(main_vb), main_tb, FALSE, FALSE, 0);
2911     gtk_table_set_col_spacings(GTK_TABLE(main_tb), 10);
2912
2913     label = gtk_label_new(ep_strdup_printf("%s:", pref->title));
2914     gtk_table_attach_defaults(GTK_TABLE(main_tb), label, 0, 1, 1, 2);
2915     gtk_misc_set_alignment(GTK_MISC(label), 1.0f, 0.5f);
2916     if (pref->description)
2917         gtk_tooltips_set_tip(tooltips, label, pref->description, NULL);
2918
2919     entry = gtk_entry_new();
2920     gtk_table_attach_defaults(GTK_TABLE(main_tb), entry, 1, 2, 1, 2);
2921     gtk_entry_set_text(GTK_ENTRY(entry), value);
2922     if (pref->description)
2923         gtk_tooltips_set_tip(tooltips, entry, pref->description, NULL);
2924
2925     bbox = dlg_button_row_new(GTK_STOCK_CANCEL,GTK_STOCK_OK, NULL);
2926     gtk_box_pack_end(GTK_BOX(main_vb), bbox, FALSE, FALSE, 0);
2927
2928     ok_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_OK);
2929     g_object_set_data (G_OBJECT(ok_bt), "module", module);
2930     g_object_set_data (G_OBJECT(ok_bt), "entry", entry);
2931     g_object_set_data (G_OBJECT(ok_bt), "pref", pref);
2932     g_signal_connect(ok_bt, "clicked", G_CALLBACK(menu_prefs_change_ok), win);
2933
2934     dlg_set_activate(entry, ok_bt);
2935
2936     cancel_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_CANCEL);
2937     g_signal_connect(cancel_bt, "clicked", G_CALLBACK(menu_prefs_change_cancel), win);
2938     window_set_cancel_button(win, cancel_bt, NULL);
2939
2940     gtk_widget_grab_default(ok_bt);
2941     gtk_widget_show_all(win);
2942     g_free(value);
2943 }
2944
2945 static guint
2946 add_protocol_prefs_menu (pref_t *pref, gpointer data)
2947 {
2948     GtkWidget *menu_preferences;
2949     GtkWidget *menu_item, *menu_sub_item, *sub_menu;
2950     GSList *group = NULL;
2951     module_t *module = data;
2952     const enum_val_t *enum_valp;
2953     gchar *label = NULL;
2954
2955     switch (pref->type) {
2956     case PREF_UINT:
2957         switch (pref->info.base) {
2958         case 8:
2959             label = g_strdup_printf ("%s: %o", pref->title, *pref->varp.uint);
2960             break;
2961         case 10:
2962             label = g_strdup_printf ("%s: %u", pref->title, *pref->varp.uint);
2963             break;
2964         case 16:
2965             label = g_strdup_printf ("%s: %x", pref->title, *pref->varp.uint);
2966             break;
2967         default:
2968             g_assert_not_reached();
2969             break;
2970         }
2971         menu_item = gtk_menu_item_new_with_label(label);
2972         g_object_set_data (G_OBJECT(menu_item), "module", module);
2973         g_signal_connect(menu_item, "activate", G_CALLBACK(menu_prefs_edit_dlg), pref);
2974         g_free (label);
2975         break;
2976     case PREF_BOOL:
2977         menu_item = gtk_check_menu_item_new_with_label(pref->title);
2978         gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM(menu_item), *pref->varp.boolp);
2979         g_object_set_data (G_OBJECT(menu_item), "module", module);
2980         g_signal_connect(menu_item, "activate", G_CALLBACK(menu_prefs_toggle_bool), pref->varp.boolp);
2981         break;
2982     case PREF_ENUM:
2983         menu_item = gtk_menu_item_new_with_label(pref->title);
2984         sub_menu = gtk_menu_new();
2985         gtk_menu_item_set_submenu (GTK_MENU_ITEM(menu_item), sub_menu);
2986         enum_valp = pref->info.enum_info.enumvals;
2987         while (enum_valp->name != NULL) {
2988             menu_sub_item = gtk_radio_menu_item_new_with_label(group, enum_valp->description);
2989             group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (menu_sub_item));
2990             if (enum_valp->value == *pref->varp.enump) {
2991                 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM(menu_sub_item), TRUE);
2992             }
2993             g_object_set_data (G_OBJECT(menu_sub_item), "module", module);
2994             g_object_set_data (G_OBJECT(menu_sub_item), "enumval", GINT_TO_POINTER(enum_valp->value));
2995             g_signal_connect(menu_sub_item, "activate", G_CALLBACK(menu_prefs_change_enum), pref->varp.enump);
2996             gtk_menu_shell_append (GTK_MENU_SHELL(sub_menu), menu_sub_item);
2997             gtk_widget_show (menu_sub_item);
2998             enum_valp++;
2999         }
3000         break;
3001     case PREF_STRING:
3002         label = g_strdup_printf ("%s: %s", pref->title, *pref->varp.string);
3003         menu_item = gtk_menu_item_new_with_label(label);
3004         g_object_set_data (G_OBJECT(menu_item), "module", module);
3005         g_signal_connect(menu_item, "activate", G_CALLBACK(menu_prefs_edit_dlg), pref);
3006         g_free (label);
3007         break;
3008     case PREF_RANGE:
3009         label = g_strdup_printf ("%s: %s", pref->title, range_convert_range (*pref->varp.range));
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_UAT:
3016         label = g_strdup_printf ("%s...", pref->title);
3017         menu_item = gtk_menu_item_new_with_label(label);
3018         g_signal_connect (menu_item, "activate", G_CALLBACK(uat_window_cb), pref->varp.uat);
3019         g_free (label);
3020         break;
3021     case PREF_STATIC_TEXT:
3022     case PREF_OBSOLETE:
3023     default:
3024         /* Nothing to add */
3025         return 0;
3026     }
3027
3028     menu_preferences = gtk_item_factory_get_widget(tree_view_menu_factory, "/Protocol Preferences");
3029     sub_menu = gtk_menu_item_get_submenu (GTK_MENU_ITEM(menu_preferences));
3030     gtk_menu_shell_append (GTK_MENU_SHELL(sub_menu), menu_item);
3031     gtk_widget_show (menu_item);
3032
3033     return 0;
3034 }
3035
3036 static void
3037 rebuild_protocol_prefs_menu (module_t *prefs, gboolean preferences)
3038 {
3039     GtkWidget *menu_preferences, *menu_item;
3040     GtkWidget *sub_menu;
3041     gchar *label;
3042
3043     menu_preferences = gtk_item_factory_get_widget(tree_view_menu_factory, "/Protocol Preferences");
3044
3045     if (preferences) {
3046         sub_menu = gtk_menu_new();
3047         gtk_menu_item_set_submenu (GTK_MENU_ITEM(menu_preferences), sub_menu);
3048
3049         label = g_strdup_printf ("%s Preferences...", prefs->description);
3050         menu_item = gtk_image_menu_item_new_with_label (label);
3051         gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM(menu_item), 
3052                                        gtk_image_new_from_stock(GTK_STOCK_PREFERENCES, GTK_ICON_SIZE_MENU));
3053         gtk_menu_shell_append (GTK_MENU_SHELL(sub_menu), menu_item);
3054         g_signal_connect_swapped(GTK_OBJECT(menu_item), "activate",
3055                                  G_CALLBACK(properties_cb), (GtkObject *) menu_item);
3056         gtk_widget_show (menu_item);
3057         g_free (label);
3058
3059         menu_item = gtk_menu_item_new();
3060         gtk_menu_shell_append (GTK_MENU_SHELL(sub_menu), menu_item);
3061         gtk_widget_show (menu_item);
3062
3063         prefs_pref_foreach(prefs, add_protocol_prefs_menu, prefs);
3064     } else {
3065         /* No preferences, remove sub menu */
3066         gtk_menu_item_set_submenu (GTK_MENU_ITEM(menu_preferences), NULL);
3067     }
3068
3069 }
3070
3071 void
3072 set_menus_for_selected_tree_row(capture_file *cf)
3073 {
3074     gboolean properties;
3075     gint id;
3076
3077     if (cf->finfo_selected != NULL) {
3078         header_field_info *hfinfo = cf->finfo_selected->hfinfo;
3079         const char *abbrev;
3080         char *prev_abbrev;
3081
3082         if (hfinfo->parent == -1) {
3083             abbrev = hfinfo->abbrev;
3084             id = (hfinfo->type == FT_PROTOCOL) ? proto_get_id((protocol_t *)hfinfo->strings) : -1;
3085         } else {
3086             abbrev = proto_registrar_get_abbrev(hfinfo->parent);
3087             id = hfinfo->parent;
3088         }
3089         properties = prefs_is_registered_protocol(abbrev);
3090
3091         set_menu_sensitivity(main_menu_factory,
3092                              "/File/Export/Selected Packet Bytes...", TRUE);
3093         set_menu_sensitivity(main_menu_factory,
3094                              "/Go/Go to Corresponding Packet", hfinfo->type == FT_FRAMENUM);
3095         set_menu_sensitivity(tree_view_menu_factory,
3096                              "/Go to Corresponding Packet", hfinfo->type == FT_FRAMENUM);
3097         set_menu_sensitivity(main_menu_factory, "/Edit/Copy/Description",
3098                              proto_can_match_selected(cf->finfo_selected, cf->edt));
3099         set_menu_sensitivity(main_menu_factory, "/Edit/Copy/Fieldname",
3100                              proto_can_match_selected(cf->finfo_selected, cf->edt));
3101         set_menu_sensitivity(main_menu_factory, "/Edit/Copy/Value",
3102                              proto_can_match_selected(cf->finfo_selected, cf->edt));
3103         set_menu_sensitivity(main_menu_factory, "/Edit/Copy/As Filter",
3104                              proto_can_match_selected(cf->finfo_selected, cf->edt));
3105         set_menu_sensitivity(tree_view_menu_factory, "/Copy",
3106                              TRUE);
3107         set_menu_sensitivity(tree_view_menu_factory, "/Copy/As Filter",
3108                              proto_can_match_selected(cf->finfo_selected, cf->edt));
3109         set_menu_sensitivity(main_menu_factory, "/Analyze/Apply as Filter",
3110                              proto_can_match_selected(cf->finfo_selected, cf->edt));
3111         set_menu_sensitivity(tree_view_menu_factory, "/Apply as Filter",
3112                              proto_can_match_selected(cf->finfo_selected, cf->edt));
3113         set_menu_sensitivity(main_menu_factory, "/Analyze/Prepare a Filter",
3114                              proto_can_match_selected(cf->finfo_selected, cf->edt));
3115         set_menu_sensitivity(tree_view_menu_factory, "/Prepare a Filter",
3116                              proto_can_match_selected(cf->finfo_selected, cf->edt));
3117         set_menu_sensitivity(tree_view_menu_factory, "/Colorize with Filter",
3118                              proto_can_match_selected(cf->finfo_selected, cf->edt));
3119         set_menu_sensitivity(tree_view_menu_factory, "/Protocol Preferences",
3120                              properties);
3121         set_menu_sensitivity(tree_view_menu_factory, "/Disable Protocol...",
3122                              (id == -1) ? FALSE : proto_can_toggle_protocol(id));
3123         set_menu_sensitivity(main_menu_factory, "/View/Expand Subtrees", cf->finfo_selected->tree_type != -1);
3124         set_menu_sensitivity(tree_view_menu_factory, "/Expand Subtrees", cf->finfo_selected->tree_type != -1);
3125         set_menu_sensitivity(tree_view_menu_factory, "/Wiki Protocol Page",
3126                              TRUE);
3127         set_menu_sensitivity(tree_view_menu_factory, "/Filter Field Reference",
3128                              TRUE);
3129         
3130         prev_abbrev = g_object_get_data(G_OBJECT(tree_view_menu_factory), "menu_abbrev");
3131         if (!prev_abbrev || (strcmp (prev_abbrev, abbrev) != 0)) {
3132             /* No previous protocol or protocol changed - update Protocol Preferences menu */
3133             module_t *prefs = prefs_find_module(abbrev);
3134             rebuild_protocol_prefs_menu (prefs, properties);
3135
3136             g_object_set_data(G_OBJECT(tree_view_menu_factory), "menu_abbrev", g_strdup(abbrev));
3137             g_free (prev_abbrev);
3138         }
3139     } else {
3140         set_menu_sensitivity(main_menu_factory,
3141                              "/File/Export/Selected Packet Bytes...", FALSE);
3142         set_menu_sensitivity(main_menu_factory,
3143                              "/Go/Go to Corresponding Packet", FALSE);
3144         set_menu_sensitivity(tree_view_menu_factory,
3145                              "/Go to Corresponding Packet", FALSE);
3146         set_menu_sensitivity(main_menu_factory, "/Edit/Copy/Description", FALSE);
3147         set_menu_sensitivity(main_menu_factory, "/Edit/Copy/Fieldname", FALSE);
3148         set_menu_sensitivity(main_menu_factory, "/Edit/Copy/Value", FALSE);
3149         set_menu_sensitivity(main_menu_factory, "/Edit/Copy/As Filter", FALSE);
3150         set_menu_sensitivity(tree_view_menu_factory, "/Copy", FALSE);
3151         set_menu_sensitivity(main_menu_factory, "/Analyze/Apply as Filter", FALSE);
3152         set_menu_sensitivity(tree_view_menu_factory, "/Apply as Filter", FALSE);
3153         set_menu_sensitivity(main_menu_factory, "/Analyze/Prepare a Filter", FALSE);
3154         set_menu_sensitivity(tree_view_menu_factory, "/Prepare a Filter", FALSE);
3155         set_menu_sensitivity(tree_view_menu_factory, "/Colorize with Filter", FALSE);
3156         set_menu_sensitivity(tree_view_menu_factory, "/Protocol Preferences",
3157                              FALSE);
3158         set_menu_sensitivity(tree_view_menu_factory, "/Disable Protocol...", FALSE);
3159         set_menu_sensitivity(main_menu_factory, "/View/Expand Subtrees", FALSE);
3160         set_menu_sensitivity(tree_view_menu_factory, "/Expand Subtrees", FALSE);
3161         set_menu_sensitivity(tree_view_menu_factory, "/Wiki Protocol Page",
3162                              FALSE);
3163         set_menu_sensitivity(tree_view_menu_factory, "/Filter Field Reference",
3164                              FALSE);
3165     }
3166
3167     walk_menu_tree_for_selected_tree_row(tap_menu_tree_root, cf->finfo_selected);
3168 }
3169
3170 void set_menus_for_packet_history(gboolean back_history, gboolean forward_history) {
3171
3172     set_menu_sensitivity(main_menu_factory, "/Go/Back", back_history);
3173     set_menu_sensitivity(main_menu_factory, "/Go/Forward", forward_history);
3174
3175     set_toolbar_for_packet_history(back_history, forward_history);
3176 }
3177
3178
3179 void set_menus_for_file_set(gboolean file_set, gboolean previous_file, gboolean next_file) {
3180
3181     set_menu_sensitivity(main_menu_factory, "/File/File Set/List Files", file_set);
3182     set_menu_sensitivity(main_menu_factory, "/File/File Set/Previous File", previous_file);
3183     set_menu_sensitivity(main_menu_factory, "/File/File Set/Next File", next_file);
3184 }
3185
3186 /*
3187  * Editor modelines
3188  *
3189  * Local Variables:
3190  * c-basic-offset: 4
3191  * tab-width: 8
3192  * indent-tabs-mode: nil
3193  * End:
3194  *
3195  * ex: set shiftwidth=4 tabstop=8 expandtab
3196  * :indentSize=4:tabSize=8:noTabs=true:
3197  */
3198