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