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