add 12 new toolbar/menu icons
[obnox/wireshark/wip.git] / gtk / menu.c
1 /* menu.c
2  * Menu routines
3  *
4  * $Id$
5  *
6  * Ethereal - Network traffic analyzer
7  * By Gerald Combs <gerald@ethereal.com>
8  * Copyright 1998 Gerald Combs
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License
12  * as published by the Free Software Foundation; either version 2
13  * of the License, or (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
23  */
24
25 #ifdef HAVE_CONFIG_H
26 # include "config.h"
27 #endif
28
29 #include <gtk/gtk.h>
30
31 #include <string.h>
32
33 #include "main.h"
34 #include "menu.h"
35 #include "tap_menu.h"
36 #include <epan/packet.h>
37 #include <epan/addr_resolv.h>
38 #include <epan/prefs.h>
39 #include <epan/tap.h>
40 #include <epan/timestamp.h>
41 #include <epan/ipproto.h>
42
43 #include "about_dlg.h"
44 #include "capture_dlg.h"
45 #include "color_dlg.h"
46 #include "filter_dlg.h"
47 #include "dlg_utils.h"
48 #include "file_dlg.h"
49 #include "find_dlg.h"
50 #include "goto_dlg.h"
51 #include "summary_dlg.h"
52 #include "prefs_dlg.h"
53 #include "packet_win.h"
54 #include "print.h"
55 #include "follow_dlg.h"
56 #include "decode_as_dlg.h"
57 #include "help_dlg.h"
58 #include "supported_protos_dlg.h"
59 #include "proto_dlg.h"
60 #include "proto_hier_stats_dlg.h"
61 #include "keys.h"
62 #include <epan/plugins.h>
63 #include <epan/epan_dissect.h>
64 #include "compat_macros.h"
65 #include "toolbar.h"
66 #include "gtkglobals.h"
67 #include "register.h"
68 #include "../menu.h"
69 #include "packet_list.h"
70 #include "ethclist.h"
71 #include "recent.h"
72 #include "../ui_util.h"
73 #include "proto_draw.h"
74 #include "conversations_table.h"
75 #include "hostlist_table.h"
76 #include "simple_dialog.h"
77 #include "packet_history.h"
78 #include "color_filters.h"
79
80 GtkWidget *popup_menu_object;
81
82 static void
83 clear_menu_recent_capture_file_cmd_cb(GtkWidget *w, gpointer unused _U_);
84
85 typedef struct _menu_item {
86     char    *name;
87     gint    group;
88     gboolean enabled;
89     GtkItemFactoryCallback callback;
90     gpointer callback_data;
91     gboolean (*selected_packet_enabled)(frame_data *, epan_dissect_t *);
92     gboolean (*selected_tree_row_enabled)(field_info *);
93     GList *children;
94 } menu_item_t;
95
96 static GList *tap_menu_tree_root = NULL;
97
98 static void 
99 merge_all_tap_menus(GList *node);
100
101 #define GTK_MENU_FUNC(a) ((GtkItemFactoryCallback)(a))
102
103 static void menus_init(void);
104 static void set_menu_sensitivity (GtkItemFactory *, const gchar *, gint);
105 static void main_toolbar_show_cb(GtkWidget *w _U_, gpointer d _U_);
106 static void filter_toolbar_show_cb(GtkWidget *w _U_, gpointer d _U_);
107 static void packet_list_show_cb(GtkWidget *w _U_, gpointer d _U_);
108 static void tree_view_show_cb(GtkWidget *w _U_, gpointer d _U_);
109 static void byte_view_show_cb(GtkWidget *w _U_, gpointer d _U_);
110 static void statusbar_show_cb(GtkWidget *w _U_, gpointer d _U_);
111 static void timestamp_absolute_cb(GtkWidget *w _U_, gpointer d _U_);
112 static void timestamp_absolute_date_cb(GtkWidget *w _U_, gpointer d _U_);
113 static void timestamp_relative_cb(GtkWidget *w _U_, gpointer d _U_);
114 static void timestamp_delta_cb(GtkWidget *w _U_, gpointer d _U_);
115 static void name_resolution_mac_cb(GtkWidget *w _U_, gpointer d _U_);
116 static void name_resolution_network_cb(GtkWidget *w _U_, gpointer d _U_);
117 static void name_resolution_transport_cb(GtkWidget *w _U_, gpointer d _U_);
118 #ifdef HAVE_LIBPCAP
119 static void auto_scroll_live_cb(GtkWidget *w _U_, gpointer d _U_);
120 #endif
121 static void colorize_cb(GtkWidget *w _U_, gpointer d _U_);
122
123 /* This is the GtkItemFactoryEntry structure used to generate new menus.
124        Item 1: The menu path. The letter after the underscore indicates an
125                accelerator key once the menu is open.
126        Item 2: The accelerator key for the entry
127        Item 3: The callback function.
128        Item 4: The callback action.  This changes the parameters with
129                which the function is called.  The default is 0.
130        Item 5: The item type, used to define what kind of an item it is.
131                Here are the possible values:
132
133                NULL               -> "<Item>"
134                ""                 -> "<Item>"
135                "<Title>"          -> create a title item
136                "<Item>"           -> create a simple item
137                "<ImageItem>"      -> create an item holding an image (gtk2)
138                "<StockItem>"      -> create an item holding a stock image (gtk2)
139                "<CheckItem>"      -> create a check item
140                "<ToggleItem>"     -> create a toggle item
141                "<RadioItem>"      -> create a radio item
142                <path>             -> path of a radio item to link against
143                "<Separator>"      -> create a separator
144                "<Tearoff>"        -> create a tearoff separator (gtk2)
145                "<Branch>"         -> create an item to hold sub items (optional)
146                "<LastBranch>"     -> create a right justified branch
147        Item 6: extra data needed for ImageItem and StockItem (gtk2)
148     */
149
150 /*  As a general GUI guideline, we try to follow the Gnome Human Interface Guidelines, which can be found at:
151     http://developer.gnome.org/projects/gup/hig/1.0/index.html
152     
153 Please note: there are some differences between the Gnome HIG menu suggestions and our implementation:
154
155 File/Open Recent:   the Gnome HIG suggests putting the list of recently used files as elements into the File menuitem.
156                     As this is ok for only a few items, this will become unhandy for 10 or even more list entries.
157                     For this reason, we use a submenu for this.
158
159 File/Close:         the Gnome HIG suggests putting this item just above the Quit item.
160                     This results in unintuitive behaviour as both Close and Quit items are very near together.
161                     By putting the Close item near the open item(s), it better suggests that it will close the 
162                     currently opened/captured file only.
163 */
164
165
166 /* main menu */
167 static GtkItemFactoryEntry menu_items[] =
168 {
169     ITEM_FACTORY_ENTRY("/_File", NULL, NULL, 0, "<Branch>", NULL),
170     ITEM_FACTORY_STOCK_ENTRY("/File/_Open...", "<control>O", file_open_cmd_cb,
171                              0, GTK_STOCK_OPEN),
172     ITEM_FACTORY_ENTRY("/File/Open _Recent", NULL, NULL, 0, "<Branch>", NULL),
173     ITEM_FACTORY_ENTRY("/File/_Merge...", NULL, file_merge_cmd_cb, 0, NULL, NULL),
174     ITEM_FACTORY_STOCK_ENTRY("/File/_Close", "<control>W", file_close_cmd_cb,
175                              0, GTK_STOCK_CLOSE),
176     ITEM_FACTORY_ENTRY("/File/<separator>", NULL, NULL, 0, "<Separator>", NULL),
177     ITEM_FACTORY_STOCK_ENTRY("/File/_Save", "<control>S", file_save_cmd_cb,
178                              0, GTK_STOCK_SAVE),
179     ITEM_FACTORY_STOCK_ENTRY("/File/Save _As...", "<shift><control>S", file_save_as_cmd_cb,
180                              0, GTK_STOCK_SAVE_AS),
181     ITEM_FACTORY_ENTRY("/File/<separator>", NULL, NULL, 0, "<Separator>", NULL),
182     ITEM_FACTORY_ENTRY("/File/_Export", NULL, NULL, 0, "<Branch>", NULL),
183     ITEM_FACTORY_ENTRY("/File/Export/as \"Plain _Text\" file...", NULL, export_text_cmd_cb,
184                              0, NULL, NULL),
185     ITEM_FACTORY_ENTRY("/File/Export/as \"_PostScript\" file...", NULL, export_ps_cmd_cb,
186                              0, NULL, NULL),
187     ITEM_FACTORY_ENTRY("/File/Export/as \"_CSV\" (Comma Separated Values packet summary) file...",
188                              NULL, export_csv_cmd_cb, 0, NULL, NULL),
189     ITEM_FACTORY_ENTRY("/File/Export/<separator>", NULL, NULL, 0, "<Separator>", NULL),
190     ITEM_FACTORY_ENTRY("/File/Export/as XML - \"P_SML\" (packet summary) file...", NULL, export_psml_cmd_cb,
191                              0, NULL, NULL),
192     ITEM_FACTORY_ENTRY("/File/Export/as XML - \"P_DML\" (packet details) file...", NULL, export_pdml_cmd_cb,
193                              0, NULL, NULL),
194     ITEM_FACTORY_ENTRY("/File/Export/<separator>", NULL, NULL, 0, "<Separator>", NULL),
195     ITEM_FACTORY_ENTRY("/File/Export/Selected Packet _Bytes...", "<control>H", savehex_cb,
196                              0, NULL, NULL),
197     ITEM_FACTORY_ENTRY("/File/<separator>", NULL, NULL, 0, "<Separator>", NULL),
198     ITEM_FACTORY_STOCK_ENTRY("/File/_Print...", "<control>P", file_print_cmd_cb,
199                              0, GTK_STOCK_PRINT),
200     ITEM_FACTORY_ENTRY("/File/<separator>", NULL, NULL, 0, "<Separator>", NULL),
201     ITEM_FACTORY_STOCK_ENTRY("/File/_Quit", "<control>Q", file_quit_cmd_cb,
202                              0, GTK_STOCK_QUIT),
203     ITEM_FACTORY_ENTRY("/_Edit", NULL, NULL, 0, "<Branch>", NULL),
204 #if 0
205     /* Un-#if this when we actually implement Cut/Copy/Paste. */
206     ITEM_FACTORY_STOCK_ENTRY("/Edit/Cut", "<control>X", NULL,
207                              0, GTK_STOCK_CUT),
208     ITEM_FACTORY_STOCK_ENTRY("/Edit/Copy", "<control>C", NULL,
209                              0, GTK_STOCK_COPY),
210     ITEM_FACTORY_STOCK_ENTRY("/Edit/Paste", "<control>V", NULL,
211                              0, GTK_STOCK_PASTE),
212     ITEM_FACTORY_ENTRY("/Edit/<separator>", NULL, NULL, 0, "<Separator>"),
213 #endif
214     ITEM_FACTORY_STOCK_ENTRY("/Edit/_Find Packet...", "<control>F",
215                              find_frame_cb, 0, GTK_STOCK_FIND),
216     ITEM_FACTORY_ENTRY("/Edit/Find Ne_xt", "<control>N", find_next_cb, 0, NULL, NULL),
217     ITEM_FACTORY_ENTRY("/Edit/Find Pre_vious", "<control>B", find_previous_cb, 0, NULL, NULL),
218     ITEM_FACTORY_ENTRY("/Edit/<separator>", NULL, NULL, 0, "<Separator>", NULL),
219     ITEM_FACTORY_ENTRY("/Edit/_Time Reference", NULL, NULL, 0, "<Branch>", NULL),
220     ITEM_FACTORY_STOCK_ENTRY("/Edit/Time Reference/Set Time Reference (toggle)", "<control>T", reftime_frame_cb, 
221                         REFTIME_TOGGLE, ETHEREAL_STOCK_TIME),
222     ITEM_FACTORY_ENTRY("/Edit/Time Reference/Find Next", NULL, reftime_frame_cb, REFTIME_FIND_NEXT, NULL, NULL),
223     ITEM_FACTORY_ENTRY("/Edit/Time Reference/Find Previous", NULL, reftime_frame_cb, REFTIME_FIND_PREV, NULL, NULL),
224     ITEM_FACTORY_ENTRY("/Edit/_Mark Packet (toggle)", "<control>M", mark_frame_cb,
225                        0, NULL, NULL),
226     ITEM_FACTORY_ENTRY("/Edit/Mark _All Packets", NULL, mark_all_frames_cb,
227                        0, NULL, NULL),
228     ITEM_FACTORY_ENTRY("/Edit/_Unmark All Packets", NULL, unmark_all_frames_cb,
229                        0, NULL, NULL),
230     ITEM_FACTORY_ENTRY("/Edit/<separator>", NULL, NULL, 0, "<Separator>", NULL),
231     ITEM_FACTORY_STOCK_ENTRY("/Edit/_Preferences...", "<shift><control>P", prefs_cb,
232                              0, GTK_STOCK_PREFERENCES),
233     ITEM_FACTORY_ENTRY("/_View", NULL, NULL, 0, "<Branch>", NULL),
234     ITEM_FACTORY_ENTRY("/View/_Main Toolbar", NULL, main_toolbar_show_cb, 0, "<CheckItem>", NULL),
235     ITEM_FACTORY_ENTRY("/View/_Filter Toolbar", NULL, filter_toolbar_show_cb, 0, "<CheckItem>", NULL),
236     ITEM_FACTORY_ENTRY("/View/_Statusbar", NULL, statusbar_show_cb, 0, "<CheckItem>", NULL),
237     ITEM_FACTORY_ENTRY("/View/<separator>", NULL, NULL, 0, "<Separator>", NULL),
238     ITEM_FACTORY_ENTRY("/View/Packet _List", NULL, packet_list_show_cb, 0, "<CheckItem>", NULL),
239     ITEM_FACTORY_ENTRY("/View/Packet _Details", NULL, tree_view_show_cb, 0, "<CheckItem>", NULL),
240     ITEM_FACTORY_ENTRY("/View/Packet _Bytes", NULL, byte_view_show_cb, 0, "<CheckItem>", NULL),
241     ITEM_FACTORY_ENTRY("/View/<separator>", NULL, NULL, 0, "<Separator>", NULL),
242     ITEM_FACTORY_ENTRY("/View/_Time Display Format", NULL, NULL, 0, "<Branch>", NULL),
243     ITEM_FACTORY_ENTRY("/View/Time Display Format/Time of Day", NULL, timestamp_absolute_cb, 
244                         0, "<RadioItem>", NULL),
245     ITEM_FACTORY_ENTRY("/View/Time Display Format/Date and Time of Day", NULL, timestamp_absolute_date_cb, 
246                         0, "/View/Time Display Format/Time of Day", NULL),
247     ITEM_FACTORY_ENTRY("/View/Time Display Format/Seconds Since Beginning of Capture", NULL, timestamp_relative_cb, 
248                         0, "/View/Time Display Format/Time of Day", NULL),
249     ITEM_FACTORY_ENTRY("/View/Time Display Format/Seconds Since Previous Packet", NULL, timestamp_delta_cb, 
250                         0, "/View/Time Display Format/Time of Day", NULL),
251     ITEM_FACTORY_ENTRY("/View/Name Resol_ution", NULL, NULL, 0, "<Branch>", NULL),
252     ITEM_FACTORY_ENTRY("/View/Name Resolution/_Resolve Name", NULL, resolve_name_cb, 0, NULL, NULL),
253     ITEM_FACTORY_ENTRY("/View/Name Resolution/<separator>", NULL, NULL, 0, "<Separator>", NULL),
254     ITEM_FACTORY_ENTRY("/View/Name Resolution/Enable for _MAC Layer", NULL, name_resolution_mac_cb, 0, "<CheckItem>", NULL),
255     ITEM_FACTORY_ENTRY("/View/Name Resolution/Enable for _Network Layer", NULL, name_resolution_network_cb, 0, "<CheckItem>", NULL),
256     ITEM_FACTORY_ENTRY("/View/Name Resolution/Enable for _Transport Layer", NULL, name_resolution_transport_cb, 0, "<CheckItem>", NULL),
257     ITEM_FACTORY_ENTRY("/View/Colorize Packet List", NULL, colorize_cb, 0, "<CheckItem>", NULL),
258 #ifdef HAVE_LIBPCAP
259     ITEM_FACTORY_ENTRY("/View/Auto Scroll in Li_ve Capture", NULL, auto_scroll_live_cb, 0, "<CheckItem>", NULL),
260 #endif
261     ITEM_FACTORY_ENTRY("/View/<separator>", NULL, NULL, 0, "<Separator>", NULL),
262     ITEM_FACTORY_STOCK_ENTRY("/View/_Zoom In", "<control>plus", view_zoom_in_cb,
263                              0, GTK_STOCK_ZOOM_IN),
264     ITEM_FACTORY_STOCK_ENTRY("/View/Zoom _Out", "<control>minus", view_zoom_out_cb,
265                              0, GTK_STOCK_ZOOM_OUT),
266     ITEM_FACTORY_STOCK_ENTRY("/View/_Normal Size", "<control>equal", view_zoom_100_cb,
267                              0, GTK_STOCK_ZOOM_100),
268     ITEM_FACTORY_STOCK_ENTRY("/View/Resize All Columns", NULL, packet_list_resize_columns_cb,
269                        0, ETHEREAL_STOCK_RESIZE_COLUMNS),
270     ITEM_FACTORY_ENTRY("/View/<separator>", NULL, NULL, 0, "<Separator>", NULL),
271     ITEM_FACTORY_ENTRY("/View/Collapse _All", NULL, collapse_all_cb,
272                        0, NULL, NULL),
273     ITEM_FACTORY_ENTRY("/View/_Expand All", NULL, expand_all_cb,
274                        0, NULL, NULL),
275     ITEM_FACTORY_ENTRY("/View/Expand Tree", NULL, expand_tree_cb, 0, NULL, NULL),
276     ITEM_FACTORY_ENTRY("/View/<separator>", NULL, NULL, 0, "<Separator>", NULL),
277     ITEM_FACTORY_STOCK_ENTRY("/View/_Coloring Rules...", NULL, color_display_cb,
278                        0, GTK_STOCK_SELECT_COLOR),
279     ITEM_FACTORY_ENTRY("/View/<separator>", NULL, NULL, 0, "<Separator>", NULL),
280     ITEM_FACTORY_ENTRY("/View/Show Packet in New _Window", NULL,
281                        new_window_cb, 0, NULL, NULL),
282     ITEM_FACTORY_STOCK_ENTRY("/View/_Reload", "<control>R", file_reload_cmd_cb,
283                              0, GTK_STOCK_REFRESH),
284     ITEM_FACTORY_ENTRY("/_Go", NULL, NULL, 0, "<Branch>", NULL),
285     ITEM_FACTORY_STOCK_ENTRY("/Go/_Back", "<alt>Left",
286                              history_back_cb, 0, GTK_STOCK_GO_BACK),
287     ITEM_FACTORY_STOCK_ENTRY("/Go/_Forward", "<alt>Right",
288                              history_forward_cb, 0, GTK_STOCK_GO_FORWARD),
289     ITEM_FACTORY_STOCK_ENTRY("/Go/_Go to Packet...", "<control>G",
290                              goto_frame_cb, 0, GTK_STOCK_JUMP_TO),
291     ITEM_FACTORY_ENTRY("/Go/Go to _Corresponding Packet", NULL, goto_framenum_cb,
292                        0, NULL, NULL),
293     ITEM_FACTORY_ENTRY("/Go/<separator>", NULL, NULL, 0, "<Separator>", NULL),
294     ITEM_FACTORY_STOCK_ENTRY("/Go/F_irst Packet", NULL,
295                              goto_top_frame_cb, 0, GTK_STOCK_GOTO_TOP),
296     ITEM_FACTORY_STOCK_ENTRY("/Go/_Last Packet", NULL,
297                              goto_bottom_frame_cb, 0, GTK_STOCK_GOTO_BOTTOM),
298 #ifdef HAVE_LIBPCAP
299     ITEM_FACTORY_ENTRY("/_Capture", NULL, NULL, 0, "<Branch>", NULL),
300     ITEM_FACTORY_STOCK_ENTRY("/Capture/_Interfaces...", NULL,
301                              capture_if_cb, 0, ETHEREAL_STOCK_CAPTURE_INTERFACES),
302     ITEM_FACTORY_STOCK_ENTRY("/Capture/_Options...", "<control>K",
303                              capture_prep_cb, 0, ETHEREAL_STOCK_CAPTURE_OPTIONS),
304     ITEM_FACTORY_STOCK_ENTRY("/Capture/_Start", NULL,
305                              capture_start_cb, 0, ETHEREAL_STOCK_CAPTURE_START),
306     ITEM_FACTORY_STOCK_ENTRY("/Capture/S_top", "<control>E", capture_stop_cb,
307                              0, ETHEREAL_STOCK_CAPTURE_STOP),
308     ITEM_FACTORY_STOCK_ENTRY("/Capture/_Restart", NULL, capture_clear_cb,
309                              0, ETHEREAL_STOCK_CAPTURE_RESTART),
310     ITEM_FACTORY_STOCK_ENTRY("/Capture/Capture _Filters...", NULL, cfilter_dialog_cb,
311                        0, ETHEREAL_STOCK_CAPTURE_FILTER),
312 #endif /* HAVE_LIBPCAP */
313     ITEM_FACTORY_ENTRY("/_Analyze", NULL, NULL, 0, "<Branch>", NULL),
314     ITEM_FACTORY_STOCK_ENTRY("/Analyze/_Display Filters...", NULL, dfilter_dialog_cb,
315                        0, ETHEREAL_STOCK_DISPLAY_FILTER),
316     ITEM_FACTORY_ENTRY("/Analyze/Appl_y as Filter", NULL, NULL, 0, "<Branch>", NULL),
317     ITEM_FACTORY_ENTRY("/Analyze/Apply as Filter/_Selected", NULL, match_selected_ptree_cb, 
318                        MATCH_SELECTED_REPLACE|MATCH_SELECTED_APPLY_NOW, NULL, NULL),
319     ITEM_FACTORY_ENTRY("/Analyze/Apply as Filter/_Not Selected", NULL, match_selected_ptree_cb, 
320                        MATCH_SELECTED_NOT|MATCH_SELECTED_APPLY_NOW, NULL, NULL),
321     ITEM_FACTORY_ENTRY("/Analyze/Apply as Filter/... _and Selected", NULL, match_selected_ptree_cb,
322                        MATCH_SELECTED_AND|MATCH_SELECTED_APPLY_NOW, NULL, NULL),
323     ITEM_FACTORY_ENTRY("/Analyze/Apply as Filter/... _or Selected", NULL, match_selected_ptree_cb,
324                        MATCH_SELECTED_OR|MATCH_SELECTED_APPLY_NOW, NULL, NULL),
325     ITEM_FACTORY_ENTRY("/Analyze/Apply as Filter/... a_nd not Selected", NULL, match_selected_ptree_cb, 
326                        MATCH_SELECTED_AND_NOT|MATCH_SELECTED_APPLY_NOW, NULL, NULL),
327     ITEM_FACTORY_ENTRY("/Analyze/Apply as Filter/... o_r not Selected", NULL, match_selected_ptree_cb, 
328                        MATCH_SELECTED_OR_NOT|MATCH_SELECTED_APPLY_NOW, NULL, NULL),
329     ITEM_FACTORY_ENTRY("/Analyze/_Prepare a Filter", NULL, NULL, 0, "<Branch>", NULL),
330     ITEM_FACTORY_ENTRY("/Analyze/Prepare a Filter/_Selected", NULL, match_selected_ptree_cb, 
331                        MATCH_SELECTED_REPLACE, NULL, NULL),
332     ITEM_FACTORY_ENTRY("/Analyze/Prepare a Filter/_Not Selected", NULL, match_selected_ptree_cb, 
333                        MATCH_SELECTED_NOT, NULL, NULL),
334     ITEM_FACTORY_ENTRY("/Analyze/Prepare a Filter/... _and Selected", NULL, match_selected_ptree_cb,
335                        MATCH_SELECTED_AND, NULL, NULL),
336     ITEM_FACTORY_ENTRY("/Analyze/Prepare a Filter/... _or Selected", NULL, match_selected_ptree_cb,
337                        MATCH_SELECTED_OR, NULL, NULL),
338     ITEM_FACTORY_ENTRY("/Analyze/Prepare a Filter/... a_nd not Selected", NULL, match_selected_ptree_cb, 
339                        MATCH_SELECTED_AND_NOT, NULL, NULL),
340     ITEM_FACTORY_ENTRY("/Analyze/Prepare a Filter/... o_r not Selected", NULL, match_selected_ptree_cb, 
341                        MATCH_SELECTED_OR_NOT, NULL, NULL),
342     ITEM_FACTORY_ENTRY("/Analyze/<separator>", NULL, NULL, 0, "<Separator>", NULL),
343     ITEM_FACTORY_ENTRY("/Analyze/_Enabled Protocols...", "<shift><control>R", proto_cb, 0, NULL, NULL),
344     ITEM_FACTORY_ENTRY("/Analyze/Decode _As...", NULL, decode_as_cb,
345                        0, NULL, NULL),
346     ITEM_FACTORY_ENTRY("/Analyze/_User Specified Decodes...", NULL,
347                        decode_show_cb, 0, NULL, NULL),
348     ITEM_FACTORY_ENTRY("/Analyze/<separator>", NULL, NULL, 0, "<Separator>", NULL),
349     ITEM_FACTORY_ENTRY("/Analyze/_Follow TCP Stream", NULL,
350                        follow_stream_cb, 0, NULL, NULL),    
351     ITEM_FACTORY_ENTRY("/_Statistics", NULL, NULL, 0, "<Branch>", NULL),
352     ITEM_FACTORY_STOCK_ENTRY("/Statistics/_Summary", NULL, summary_open_cb, 0, GTK_STOCK_PROPERTIES),
353     ITEM_FACTORY_ENTRY("/Statistics/_Protocol Hierarchy", NULL,
354                        proto_hier_stats_cb, 0, NULL, NULL),
355     ITEM_FACTORY_STOCK_ENTRY("/Statistics/Conversations", NULL,
356                        init_conversation_notebook_cb, 0, ETHEREAL_STOCK_CONVERSATIONS),
357     ITEM_FACTORY_STOCK_ENTRY("/Statistics/Endpoints", NULL,
358                        init_hostlist_notebook_cb, 0, ETHEREAL_STOCK_ENDPOINTS),
359     ITEM_FACTORY_ENTRY("/_Help", NULL, NULL, 0, "<Branch>", NULL),
360     ITEM_FACTORY_STOCK_ENTRY("/Help/_Contents", "F1", topic_menu_cb, HELP_CONTENT, GTK_STOCK_HELP),
361     ITEM_FACTORY_ENTRY("/Help/_Supported Protocols", NULL, supported_cb, 0, NULL, NULL),
362 #if (GLIB_MAJOR_VERSION >= 2)
363 #ifdef ETHEREAL_EUG_DIR
364     ITEM_FACTORY_ENTRY("/Help/User's Guide", NULL, url_page_menu_cb, HELP_CONTENT, NULL, NULL),
365 #endif
366     ITEM_FACTORY_ENTRY("/Help/Manual Pages", NULL, NULL, 0, "<Branch>", NULL),
367     ITEM_FACTORY_ENTRY("/Help/Manual Pages/Ethereal", NULL, topic_menu_cb, LOCALPAGE_MAN_ETHEREAL, NULL, NULL),
368     ITEM_FACTORY_ENTRY("/Help/Manual Pages/Ethereal Filter", NULL, topic_menu_cb, LOCALPAGE_MAN_ETHEREAL_FILTER, NULL, NULL),
369     ITEM_FACTORY_ENTRY("/Help/Manual Pages/<separator>", NULL, NULL, 0, "<Separator>", NULL),
370     ITEM_FACTORY_ENTRY("/Help/Manual Pages/Tethereal", NULL, topic_menu_cb, LOCALPAGE_MAN_TETHEREAL, NULL, NULL),
371     ITEM_FACTORY_ENTRY("/Help/Manual Pages/Mergecap", NULL, topic_menu_cb, LOCALPAGE_MAN_MERGECAP, NULL, NULL),
372     ITEM_FACTORY_ENTRY("/Help/Manual Pages/Editcap", NULL, topic_menu_cb, LOCALPAGE_MAN_EDITCAP, NULL, NULL),
373     ITEM_FACTORY_ENTRY("/Help/Manual Pages/Text2pcap", NULL, topic_menu_cb, LOCALPAGE_MAN_TEXT2PCAP, NULL, NULL),
374     ITEM_FACTORY_ENTRY("/Help/Ethereal Online", NULL, NULL, 0, "<Branch>", NULL),
375     ITEM_FACTORY_STOCK_ENTRY("/Help/Ethereal Online/Home Page", NULL, topic_menu_cb, ONLINEPAGE_HOME, GTK_STOCK_HOME),
376     ITEM_FACTORY_STOCK_ENTRY("/Help/Ethereal Online/Wiki", NULL, topic_menu_cb, ONLINEPAGE_WIKI, ETHEREAL_STOCK_WIKI),
377     ITEM_FACTORY_STOCK_ENTRY("/Help/Ethereal Online/User's Guide", NULL, topic_menu_cb, ONLINEPAGE_USERGUIDE, ETHEREAL_STOCK_WEB_SUPPORT),
378     ITEM_FACTORY_ENTRY("/Help/Ethereal Online/FAQ's", NULL, topic_menu_cb, ONLINEPAGE_FAQ, NULL, NULL),
379     ITEM_FACTORY_ENTRY("/Help/Ethereal Online/Downloads", NULL, topic_menu_cb, ONLINEPAGE_DOWNLOAD, NULL, NULL),
380     ITEM_FACTORY_ENTRY("/Help/Ethereal Online/Example Files", NULL, topic_menu_cb, ONLINEPAGE_SAMPLE_FILES, NULL, NULL),
381 #endif
382     ITEM_FACTORY_ENTRY("/Help/<separator>", NULL, NULL, 0, "<Separator>", NULL),
383     ITEM_FACTORY_STOCK_ENTRY("/Help/_About Ethereal", NULL, about_ethereal_cb,
384                        0, ETHEREAL_STOCK_ABOUT)
385 };
386
387
388 /* calculate the number of menu_items */
389 static int nmenu_items = sizeof(menu_items) / sizeof(menu_items[0]);
390
391 /* packet list popup */
392 static GtkItemFactoryEntry packet_list_menu_items[] =
393 {
394     ITEM_FACTORY_ENTRY("/Mark Packet (toggle)", NULL, mark_frame_cb, 0, NULL, NULL),
395     ITEM_FACTORY_ENTRY("/Time Reference", NULL, NULL, 0, "<Branch>", NULL),
396     ITEM_FACTORY_STOCK_ENTRY("/Time Reference/Set Time Reference (toggle)", NULL, reftime_frame_cb, REFTIME_TOGGLE, ETHEREAL_STOCK_TIME),
397     ITEM_FACTORY_ENTRY("/Time Reference/Find Next", NULL, reftime_frame_cb, REFTIME_FIND_NEXT, NULL, NULL),
398     ITEM_FACTORY_ENTRY("/Time Reference/Find Previous", NULL, reftime_frame_cb, REFTIME_FIND_PREV, NULL, NULL),
399
400     ITEM_FACTORY_ENTRY("/<separator>", NULL, NULL, 0, "<Separator>", NULL),
401
402     ITEM_FACTORY_ENTRY("/Apply as Filter", NULL, NULL, 0, "<Branch>", NULL),
403     ITEM_FACTORY_ENTRY("/Apply as Filter/_Selected", NULL, match_selected_plist_cb, 
404                        MATCH_SELECTED_REPLACE|MATCH_SELECTED_APPLY_NOW, NULL, NULL),
405     ITEM_FACTORY_ENTRY("/Apply as Filter/_Not Selected", NULL, match_selected_plist_cb, 
406                        MATCH_SELECTED_NOT|MATCH_SELECTED_APPLY_NOW, NULL, NULL),
407     ITEM_FACTORY_ENTRY("/Apply as Filter/... _and Selected", NULL, match_selected_plist_cb, 
408                        MATCH_SELECTED_AND|MATCH_SELECTED_APPLY_NOW, NULL, NULL),
409     ITEM_FACTORY_ENTRY("/Apply as Filter/... _or Selected", NULL, match_selected_plist_cb, 
410                        MATCH_SELECTED_OR|MATCH_SELECTED_APPLY_NOW, NULL, NULL),
411     ITEM_FACTORY_ENTRY("/Apply as Filter/... a_nd not Selected", NULL, match_selected_plist_cb, 
412                        MATCH_SELECTED_AND_NOT|MATCH_SELECTED_APPLY_NOW, NULL, NULL),
413     ITEM_FACTORY_ENTRY("/Apply as Filter/... o_r not Selected", NULL, match_selected_plist_cb,
414                        MATCH_SELECTED_OR_NOT|MATCH_SELECTED_APPLY_NOW, NULL, NULL),
415
416     ITEM_FACTORY_ENTRY("/Prepare a Filter", NULL, NULL, 0, "<Branch>", NULL),
417     ITEM_FACTORY_ENTRY("/Prepare a Filter/_Selected", NULL, match_selected_plist_cb,
418                        MATCH_SELECTED_REPLACE, NULL, NULL),
419     ITEM_FACTORY_ENTRY("/Prepare a Filter/_Not Selected", NULL, match_selected_plist_cb,
420                        MATCH_SELECTED_NOT, NULL, NULL),
421     ITEM_FACTORY_ENTRY("/Prepare a Filter/... _and Selected", NULL, match_selected_plist_cb,
422                        MATCH_SELECTED_AND, NULL, NULL),
423     ITEM_FACTORY_ENTRY("/Prepare a Filter/... _or Selected", NULL, match_selected_plist_cb,
424                        MATCH_SELECTED_OR, NULL, NULL),
425     ITEM_FACTORY_ENTRY("/Prepare a Filter/... a_nd not Selected", NULL, match_selected_plist_cb,
426                        MATCH_SELECTED_AND_NOT, NULL, NULL),
427     ITEM_FACTORY_ENTRY("/Prepare a Filter/... o_r not Selected", NULL, match_selected_plist_cb,
428                        MATCH_SELECTED_OR_NOT, NULL, NULL),
429
430     ITEM_FACTORY_ENTRY("/Follow TCP Stream", NULL, follow_stream_cb,
431                        0, NULL, NULL),
432
433     ITEM_FACTORY_ENTRY("/<separator>", NULL, NULL, 0, "<Separator>", NULL),
434
435     ITEM_FACTORY_ENTRY("/Decode As...", NULL, decode_as_cb, 0, NULL, NULL),
436     ITEM_FACTORY_ENTRY("/Print...", NULL, file_print_selected_cmd_cb, 0, NULL, NULL),
437     ITEM_FACTORY_ENTRY("/Show Packet in New Window", NULL, new_window_cb,
438                        0, NULL, NULL)
439 };
440
441 static GtkItemFactoryEntry tree_view_menu_items[] =
442 {
443     ITEM_FACTORY_ENTRY("/Expand Subtrees", NULL, expand_tree_cb, 0, NULL, NULL),
444     ITEM_FACTORY_ENTRY("/Expand All", NULL, expand_all_cb, 0, NULL, NULL),
445     ITEM_FACTORY_ENTRY("/Collapse All", NULL, collapse_all_cb, 0, NULL, NULL),
446
447     ITEM_FACTORY_ENTRY("/<separator>", NULL, NULL, 0, "<Separator>", NULL),
448
449     ITEM_FACTORY_ENTRY("/Apply as Filter", NULL, NULL, 0, "<Branch>", NULL),
450     ITEM_FACTORY_ENTRY("/Apply as Filter/_Selected", NULL, match_selected_ptree_cb, 
451                        MATCH_SELECTED_REPLACE|MATCH_SELECTED_APPLY_NOW, NULL, NULL),
452     ITEM_FACTORY_ENTRY("/Apply as Filter/_Not Selected", NULL, match_selected_ptree_cb,
453                        MATCH_SELECTED_NOT|MATCH_SELECTED_APPLY_NOW, NULL, NULL),
454     ITEM_FACTORY_ENTRY("/Apply as Filter/... _and Selected", NULL, match_selected_ptree_cb,
455                        MATCH_SELECTED_AND|MATCH_SELECTED_APPLY_NOW, NULL, NULL),
456     ITEM_FACTORY_ENTRY("/Apply as Filter/... _or Selected", NULL, match_selected_ptree_cb,
457                        MATCH_SELECTED_OR|MATCH_SELECTED_APPLY_NOW, NULL, NULL),
458     ITEM_FACTORY_ENTRY("/Apply as Filter/... a_nd not Selected", NULL, match_selected_ptree_cb, 
459                        MATCH_SELECTED_AND_NOT|MATCH_SELECTED_APPLY_NOW, NULL, NULL),
460     ITEM_FACTORY_ENTRY("/Apply as Filter/... o_r not Selected", NULL, match_selected_ptree_cb,
461                        MATCH_SELECTED_OR_NOT|MATCH_SELECTED_APPLY_NOW, NULL, NULL),
462
463     ITEM_FACTORY_ENTRY("/Prepare a Filter", NULL, NULL, 0, "<Branch>", NULL),
464     ITEM_FACTORY_ENTRY("/Prepare a Filter/_Selected", NULL, match_selected_ptree_cb, 
465                        MATCH_SELECTED_REPLACE, NULL, NULL),
466     ITEM_FACTORY_ENTRY("/Prepare a Filter/_Not Selected", NULL, match_selected_ptree_cb,
467                        MATCH_SELECTED_NOT, NULL, NULL),
468     ITEM_FACTORY_ENTRY("/Prepare a Filter/... _and Selected", NULL, match_selected_ptree_cb,
469                        MATCH_SELECTED_AND, NULL, NULL),
470     ITEM_FACTORY_ENTRY("/Prepare a Filter/... _or Selected", NULL, match_selected_ptree_cb,
471                        MATCH_SELECTED_OR, NULL, NULL),
472     ITEM_FACTORY_ENTRY("/Prepare a Filter/... a_nd not Selected", NULL, match_selected_ptree_cb, 
473                        MATCH_SELECTED_AND_NOT, NULL, NULL),
474     ITEM_FACTORY_ENTRY("/Prepare a Filter/... o_r not Selected", NULL, match_selected_ptree_cb,
475                        MATCH_SELECTED_OR_NOT, NULL, NULL),
476
477     ITEM_FACTORY_ENTRY("/Follow TCP Stream", NULL, follow_stream_cb,
478                        0, NULL, NULL),
479
480     ITEM_FACTORY_ENTRY("/<separator>", NULL, NULL, 0, "<Separator>", NULL),
481
482     ITEM_FACTORY_STOCK_ENTRY("/Wiki Protocol Page", NULL, selected_ptree_info_cb,
483                        0, ETHEREAL_STOCK_WIKI),
484     ITEM_FACTORY_STOCK_ENTRY("/Filter Field Reference", NULL, selected_ptree_ref_cb,
485                        0, ETHEREAL_STOCK_INTERNET),
486     ITEM_FACTORY_ENTRY("/Protocol Preferences...", NULL, properties_cb,
487                        0, NULL, NULL),
488     ITEM_FACTORY_ENTRY("/<separator>", NULL, NULL, 0, "<Separator>", NULL),
489     ITEM_FACTORY_ENTRY("/Decode As...", NULL, decode_as_cb, 0, NULL, NULL),
490     ITEM_FACTORY_ENTRY("/_Resolve Name", NULL, resolve_name_cb, 0, NULL, NULL),
491     ITEM_FACTORY_ENTRY("/_Go to Corresponding Packet", NULL, goto_framenum_cb, 0, NULL, NULL),
492 };
493
494 static GtkItemFactoryEntry hexdump_menu_items[] =
495 {
496     ITEM_FACTORY_ENTRY("/Copy", NULL, copy_hex_cb,
497                        0, NULL, NULL),
498     ITEM_FACTORY_ENTRY("/Export Selected Packet Bytes...", NULL, savehex_cb,
499                        0, NULL, NULL),
500 };
501
502 static int initialize = TRUE;
503 static GtkItemFactory *main_menu_factory = NULL;
504 static GtkItemFactory *packet_list_menu_factory = NULL;
505 static GtkItemFactory *tree_view_menu_factory = NULL;
506 static GtkItemFactory *hexdump_menu_factory = NULL;
507
508 static GSList *popup_menu_list = NULL;
509
510 static GtkAccelGroup *grp;
511
512 GtkWidget *
513 main_menu_new(GtkAccelGroup ** table) {
514   GtkWidget *menubar;
515
516   grp = gtk_accel_group_new();
517
518   if (initialize)
519     menus_init();
520
521   menubar = main_menu_factory->widget;
522
523   if (table)
524     *table = grp;
525
526   return menubar;
527 }
528
529 static void
530 menus_init(void) {
531   if (initialize) {
532     initialize = FALSE;
533
534     /* popup */
535     packet_list_menu_factory = gtk_item_factory_new(GTK_TYPE_MENU, "<main>", NULL);
536     popup_menu_object = gtk_menu_new();
537     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);
538     OBJECT_SET_DATA(popup_menu_object, PM_PACKET_LIST_KEY,
539                     packet_list_menu_factory->widget);
540     popup_menu_list = g_slist_append((GSList *)popup_menu_list, packet_list_menu_factory);
541
542     tree_view_menu_factory = gtk_item_factory_new(GTK_TYPE_MENU, "<main>", NULL);
543     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);
544     OBJECT_SET_DATA(popup_menu_object, PM_TREE_VIEW_KEY,
545                     tree_view_menu_factory->widget);
546     popup_menu_list = g_slist_append((GSList *)popup_menu_list, tree_view_menu_factory);
547
548     hexdump_menu_factory = gtk_item_factory_new(GTK_TYPE_MENU, "<main>", NULL);
549     gtk_item_factory_create_items_ac(hexdump_menu_factory, sizeof(hexdump_menu_items)/sizeof(hexdump_menu_items[0]), hexdump_menu_items, popup_menu_object, 2);
550     OBJECT_SET_DATA(popup_menu_object, PM_HEXDUMP_KEY,
551                     hexdump_menu_factory->widget);
552     popup_menu_list = g_slist_append((GSList *)popup_menu_list, hexdump_menu_factory);
553
554     /* main */
555     main_menu_factory = gtk_item_factory_new(GTK_TYPE_MENU_BAR, "<main>", grp);
556     gtk_item_factory_create_items_ac(main_menu_factory, nmenu_items, menu_items, NULL, 2);
557
558     merge_all_tap_menus(tap_menu_tree_root);
559
560     /* Initialize enabled/disabled state of menu items */
561     set_menus_for_unsaved_capture_file(FALSE);
562     set_menus_for_capture_file(FALSE);
563 #if 0
564     /* Un-#if this when we actually implement Cut/Copy/Paste.
565        Then make sure you enable them when they can be done. */
566     set_menu_sensitivity(main_menu_factory, "/Edit/Cut", FALSE);
567     set_menu_sensitivity(main_menu_factory, "/Edit/Copy", FALSE);
568     set_menu_sensitivity(main_menu_factory, "/Edit/Paste", FALSE);
569 #endif
570
571     set_menus_for_captured_packets(FALSE);
572     set_menus_for_selected_packet(&cfile);
573     set_menus_for_selected_tree_row(&cfile);
574     set_menus_for_capture_in_progress(FALSE);
575
576     /* init with an empty recent files list */
577     clear_menu_recent_capture_file_cmd_cb(NULL, NULL);
578   }
579 }
580
581
582 gint tap_menu_item_add_compare(gconstpointer a, gconstpointer b)
583 {
584     return strcmp(
585         ((const menu_item_t *) a)->name, 
586         ((const menu_item_t *) b)->name);
587 }
588
589
590 /* add a menuitem below the current node */
591 GList * tap_menu_item_add(
592     char *name, 
593     gint group, 
594     GtkItemFactoryCallback callback,
595     gboolean (*selected_packet_enabled)(frame_data *, epan_dissect_t *),
596     gboolean (*selected_tree_row_enabled)(field_info *),
597     gpointer callback_data,
598         GList *curnode)
599 {
600     menu_item_t *curr;
601     menu_item_t *child;
602
603
604     child = g_malloc(sizeof (menu_item_t));
605     child->group            = group;
606     child->name             = name;
607     child->callback         = callback;
608     child->selected_packet_enabled = selected_packet_enabled;
609     child->selected_tree_row_enabled = selected_tree_row_enabled;
610     child->callback_data    = callback_data;
611     child->enabled          = FALSE;
612     child->children         = NULL;
613
614     /* insert the new child node into the parent */
615     curr = curnode->data;
616     curr->children = g_list_insert_sorted(curr->children, child, tap_menu_item_add_compare);
617
618     /* return the new node */
619     /* XXX: improve this */
620     return g_list_find(curr->children, child);
621 }
622
623 /*
624  * Add a new menu item for a tap.
625  * This must be called after we've created the main menu, so it can't
626  * be called from the routine that registers taps - we have to introduce
627  * another per-tap registration routine.
628  *
629  * "callback" gets called when the menu item is selected; it should do
630  * the work of creating the tap window.
631  *
632  * "selected_packet_enabled" gets called by "set_menus_for_selected_packet()";
633  * it's passed a Boolean that's TRUE if a packet is selected and FALSE
634  * otherwise, and should return TRUE if the tap will work now (which
635  * might depend on whether a packet is selected and, if one is, on the
636  * packet) and FALSE if not.
637  *
638  * "selected_tree_row_enabled" gets called by
639  * "set_menus_for_selected_tree_row()"; it's passed a Boolean that's TRUE if
640  * a protocol tree row is selected and FALSE otherwise, and should return
641  * TRUE if the tap will work now (which might depend on whether a tree row
642  * is selected and, if one is, on the tree row) and FALSE if not.
643  */
644 void
645 register_tap_menu_item(
646     char *name, 
647     REGISTER_TAP_GROUP_E group,
648     GtkItemFactoryCallback callback,
649     gboolean (*selected_packet_enabled)(frame_data *, epan_dissect_t *),
650     gboolean (*selected_tree_row_enabled)(field_info *),
651     gpointer callback_data)
652 {
653     /*static const char toolspath[] = "/Statistics/";*/
654     char *toolspath;
655     char *p;
656     char *menupath;
657     size_t menupathlen;
658     menu_item_t *child;
659     GList *curnode;
660     GList *childnode;
661
662     /*
663      * The menu path must be relative.
664      */
665     g_assert(*name != '/');
666
667     switch(group) {
668     case(REGISTER_TAP_GROUP_GENERIC): toolspath = "/Statistics/"; break;
669     case(REGISTER_TAP_GROUP_CONVERSATION_LIST): toolspath = "/Statistics/_Conversation List/"; break;
670     case(REGISTER_TAP_GROUP_ENDPOINT_LIST): toolspath = "/Statistics/_Endpoint List/"; break;
671     case(REGISTER_TAP_GROUP_RESPONSE_TIME): toolspath = "/Statistics/Service _Response Time/"; break;
672     case(REGISTER_TAP_GROUP_TELEPHONY): toolspath = "/Statistics/"; break;
673     case(REGISTER_TAP_GROUP_NONE): toolspath = "/Statistics/"; break;
674     default:
675         g_assert(0);
676         toolspath = NULL;
677     }
678
679     /* add the (empty) root node, if not already done */
680     if(tap_menu_tree_root == NULL) {
681         child = g_malloc0(sizeof (menu_item_t));
682         tap_menu_tree_root = g_list_append(NULL, child);
683     }
684
685     /*
686      * Create any submenus required.
687      */
688     curnode = tap_menu_tree_root;
689     p = name;
690     while ((p = strchr(p, '/')) != NULL) {
691         /*
692          * OK, everything between "name" and "p" is
693          * a menu relative subtree into which the menu item
694          * will be placed.
695          *
696          * Construct the absolute path name of that subtree.
697          */
698         menupathlen = strlen(toolspath) + 1 + (p - name);
699         menupath = g_malloc(menupathlen);
700         strcpy(menupath, toolspath);
701         strncat(menupath, name, p - name);
702
703         /*
704          * Does there exist an entry with that path at this
705          * level of the Analyze menu tree?
706          */
707         child = curnode->data;
708         for (childnode = child->children; childnode != NULL; childnode = childnode->next) {
709             child = childnode->data;
710             if (strcmp(child->name, menupath) == 0)
711                 break;
712         }
713         if (childnode == NULL) {
714             /*
715              * No.  Create such an item as a subtree, and
716              * add it to the Tools menu tree.
717              */
718             childnode = tap_menu_item_add(
719                 menupath, group, NULL, NULL ,NULL, NULL, curnode);
720         } else {
721             /*
722              * Yes.  We don't need this "menupath" any longer.
723              */
724             g_free(menupath);
725         }
726         curnode = childnode;
727
728         /*
729          * Skip over the '/' we found.
730          */
731         p++;
732     }
733
734     /*
735      * Construct the main menu path for the menu item.
736      */
737     menupathlen = strlen(toolspath) + 1 + strlen(name);
738     menupath = g_malloc(menupathlen);
739     strcpy(menupath, toolspath);
740     strcat(menupath, name);
741
742     /*
743      * Construct an item factory entry for the item, and add it to
744      * the main menu.
745      */
746     tap_menu_item_add(
747         menupath, group, callback, 
748         selected_packet_enabled, selected_tree_row_enabled, 
749         callback_data, curnode);
750 }
751
752
753 guint merge_tap_menus_layered(GList *node, gint group) {
754     GtkItemFactoryEntry *entry;
755     GList       *child;
756     guint       added = 0;
757     menu_item_t *node_data = node->data;
758
759     /*
760      * Is this a leaf node or an interior node?
761      */
762     if (node_data->children == NULL) {
763         /*
764          * It's a leaf node.
765          */
766
767         /*
768          * The root node doesn't correspond to a menu tree item; it
769          * has a null name pointer.
770          */
771         if (node_data->name != NULL && group == node_data->group) {
772             entry = g_malloc0(sizeof (GtkItemFactoryEntry));
773             entry->path = node_data->name;
774             entry->callback = node_data->callback;
775 #if GTK_MAJOR_VERSION >= 2
776             switch(group) {
777             case(REGISTER_TAP_GROUP_NONE):
778                 break;
779             case(REGISTER_TAP_GROUP_GENERIC):
780                 break;
781             case(REGISTER_TAP_GROUP_CONVERSATION_LIST):
782                 entry->item_type = "<StockItem>";
783                 entry->extra_data = ETHEREAL_STOCK_CONVERSATIONS;
784                 break;
785             case(REGISTER_TAP_GROUP_ENDPOINT_LIST):
786                 entry->item_type = "<StockItem>";
787                 entry->extra_data = ETHEREAL_STOCK_ENDPOINTS;
788                 break;
789             case(REGISTER_TAP_GROUP_RESPONSE_TIME):
790                 entry->item_type = "<StockItem>";
791                 entry->extra_data = ETHEREAL_STOCK_TIME;
792                 break;
793             case(REGISTER_TAP_GROUP_TELEPHONY):
794                 entry->item_type = "<StockItem>";
795                 entry->extra_data = ETHEREAL_STOCK_TELEPHONY;
796                 break;
797             default:
798                 g_assert_not_reached();
799             }
800 #endif
801             gtk_item_factory_create_item(main_menu_factory, entry, node_data->callback_data, 2);
802             set_menu_sensitivity(main_menu_factory, node_data->name, FALSE); /* no capture file yet */
803             added++;
804         }
805     } else {
806         /*
807          * It's an interior node; call
808          * "merge_tap_menus_layered()" on all its children 
809          */
810
811         /*
812          * The root node doesn't correspond to a menu tree item; it
813          * has a null name pointer.
814          */
815         if (node_data->name != NULL && group == node_data->group) {
816             entry = g_malloc0(sizeof (GtkItemFactoryEntry));
817             entry->path = node_data->name;
818             entry->item_type = "<Branch>";
819             gtk_item_factory_create_item(main_menu_factory, entry,
820                 NULL, 2);
821             set_menu_sensitivity(main_menu_factory, node_data->name,
822                 FALSE);    /* no children yet */
823             added++;
824         }
825
826         for (child = node_data->children; child != NULL; child =
827             child->next) {
828             added += merge_tap_menus_layered(child, group);
829         }
830     }
831
832     return added;
833 }
834
835
836 void merge_all_tap_menus(GList *node) {
837     GtkItemFactoryEntry *entry;
838
839     entry = g_malloc0(sizeof (GtkItemFactoryEntry));
840     entry->item_type = "<Separator>";
841     entry->path = "/Statistics/";
842
843     /* 
844      * merge only the menu items of the specific group,
845      * and then append a seperator
846      */
847     if (merge_tap_menus_layered(node, REGISTER_TAP_GROUP_GENERIC)) {
848         gtk_item_factory_create_item(main_menu_factory, entry, NULL, 2);
849     }
850     if (merge_tap_menus_layered(node, REGISTER_TAP_GROUP_CONVERSATION_LIST)) {
851         /*gtk_item_factory_create_item(main_menu_factory, entry, NULL, 2);*/
852     }
853     if (merge_tap_menus_layered(node, REGISTER_TAP_GROUP_ENDPOINT_LIST)) {
854         /*gtk_item_factory_create_item(main_menu_factory, entry, NULL, 2);*/
855     }
856     if (merge_tap_menus_layered(node, REGISTER_TAP_GROUP_RESPONSE_TIME)) {
857         gtk_item_factory_create_item(main_menu_factory, entry, NULL, 2);
858     }
859     if (merge_tap_menus_layered(node, REGISTER_TAP_GROUP_TELEPHONY)) {
860         gtk_item_factory_create_item(main_menu_factory, entry, NULL, 2);
861     }
862     if (merge_tap_menus_layered(node, REGISTER_TAP_GROUP_NONE)) {
863         /*gtk_item_factory_create_item(main_menu_factory, entry, NULL, 2);*/
864     }
865 }
866
867
868
869 /*
870  * Enable/disable menu sensitivity.
871  */
872 static void
873 set_menu_sensitivity(GtkItemFactory *ifactory, const gchar *path, gint val)
874 {
875   GSList *menu_list;
876   GtkWidget *menu_item;
877   gchar *dup;
878   gchar *dest;
879
880
881   /* the underscore character regularly confuses things, as it will prevent finding 
882    * the menu_item, so it has to be removed first */
883   dup = g_strdup(path);
884   dest = dup;
885   while(*path) {
886       if (*path != '_') {
887         *dest = *path;
888         dest++;
889       }
890       path++;
891   }
892   *dest = '\0';
893
894   if (ifactory == NULL) {
895     /*
896      * Do it for all pop-up menus.
897      */
898     for (menu_list = popup_menu_list; menu_list != NULL;
899          menu_list = g_slist_next(menu_list))
900       set_menu_sensitivity(menu_list->data, dup, val);
901   } else {
902     /*
903      * Do it for that particular menu.
904      */
905     if ((menu_item = gtk_item_factory_get_widget(ifactory, dup)) != NULL) {
906       if (GTK_IS_MENU(menu_item)) {
907         /*
908          * "dup" refers to a submenu; "gtk_item_factory_get_widget()"
909          * gets the menu, not the item that, when selected, pops up
910          * the submenu.
911          *
912          * We have to change the latter item's sensitivity, so that
913          * it shows up normally if sensitive and grayed-out if
914          * insensitive.
915          */
916         menu_item = gtk_menu_get_attach_widget(GTK_MENU(menu_item));
917       }
918       gtk_widget_set_sensitive(menu_item, val);
919     } else{
920       /* be sure this menu item *is* existing */
921       g_assert_not_reached();
922     }
923   }
924
925   g_free(dup);
926 }
927
928 void
929 set_menu_object_data_meat(GtkItemFactory *ifactory, gchar *path, gchar *key, gpointer data)
930 {
931         GtkWidget *menu = NULL;
932
933         if ((menu = gtk_item_factory_get_widget(ifactory, path)) != NULL)
934                 OBJECT_SET_DATA(menu, key, data);
935 }
936
937 void
938 set_menu_object_data (gchar *path, gchar *key, gpointer data) {
939   GSList *menu_list = popup_menu_list;
940   gchar *shortpath = strrchr(path, '/');
941
942   set_menu_object_data_meat(main_menu_factory, path, key, data);
943   while (menu_list != NULL) {
944         set_menu_object_data_meat(menu_list->data, shortpath, key, data);
945         menu_list = g_slist_next(menu_list);
946   }
947 }
948
949
950 /* Recently used capture files submenu: 
951  * Submenu containing the recently used capture files.
952  * The capture filenames are always kept with the absolute path, to be independant
953  * of the current path. 
954  * They are only stored inside the labels of the submenu (no separate list). */
955
956 #define MENU_RECENT_FILES_PATH "/File/Open Recent"
957 #define MENU_RECENT_FILES_KEY "Recent File Name"
958
959 void
960 update_menu_recent_capture_file1(GtkWidget *widget, gpointer cnt) {
961     gchar *widget_cf_name;
962
963     widget_cf_name = OBJECT_GET_DATA(widget, MENU_RECENT_FILES_KEY);
964
965     /* if this menu item is a file, count it */
966     if (widget_cf_name) {
967         (*(guint *)cnt)++;
968     }
969 }
970
971
972 /* update the menu */
973 void
974 update_menu_recent_capture_file(GtkWidget *submenu_recent_files) {
975     guint cnt = 0;
976
977     gtk_container_foreach(GTK_CONTAINER(submenu_recent_files), 
978                 update_menu_recent_capture_file1, &cnt);
979
980     /* make parent menu item sensitive only, if we have any valid files in the list */
981     set_menu_sensitivity(main_menu_factory, MENU_RECENT_FILES_PATH, cnt);
982 }
983
984
985 /* remove the capture filename from the "Recent Files" menu */
986 void
987 remove_menu_recent_capture_file(GtkWidget *widget, gpointer unused _U_) {
988     GtkWidget *submenu_recent_files;
989     gchar *widget_cf_name;
990
991
992     widget_cf_name = OBJECT_GET_DATA(widget, MENU_RECENT_FILES_KEY);
993     g_free(widget_cf_name);
994
995     /* get the submenu container item */
996     submenu_recent_files = gtk_item_factory_get_widget(main_menu_factory, MENU_RECENT_FILES_PATH);
997
998     /* XXX: is this all we need to do, to free the menu item and its label?
999        The reference count of widget will go to 0, so it'll be freed;
1000        will that free the label? */
1001     gtk_container_remove(GTK_CONTAINER(submenu_recent_files), widget);
1002 }
1003
1004
1005 /* callback, if the user pushed the <Clear File List> item */
1006 static void
1007 clear_menu_recent_capture_file_cmd_cb(GtkWidget *w _U_, gpointer unused _U_) {
1008     GtkWidget *submenu_recent_files;
1009
1010
1011     submenu_recent_files = gtk_item_factory_get_widget(main_menu_factory, MENU_RECENT_FILES_PATH);
1012
1013     gtk_container_foreach(GTK_CONTAINER(submenu_recent_files), 
1014                 remove_menu_recent_capture_file, NULL);
1015
1016     update_menu_recent_capture_file(submenu_recent_files);
1017 }
1018
1019
1020 /* callback, if the user pushed a recent file submenu item */
1021 void
1022 menu_open_recent_file_cmd(GtkWidget *w)
1023 {
1024         GtkWidget *submenu_recent_files;
1025         GtkWidget *menu_item_child;
1026         gchar     *cf_name;
1027         int       err;
1028
1029         submenu_recent_files = gtk_item_factory_get_widget(main_menu_factory, MENU_RECENT_FILES_PATH);
1030
1031         /* get capture filename from the menu item label */
1032         menu_item_child = (GTK_BIN(w))->child;
1033         gtk_label_get(GTK_LABEL(menu_item_child), &cf_name);
1034
1035         /* open and read the capture file (this will close an existing file) */
1036         if (cf_open(&cfile, cf_name, FALSE, &err) == CF_OK) {
1037                 cf_read(&cfile);
1038         } else {
1039                 /* the capture file isn't existing any longer, remove menu item */
1040                 /* XXX: ask user to remove item, it's maybe only a temporary problem */
1041                 remove_menu_recent_capture_file(w, NULL);
1042         }
1043
1044         update_menu_recent_capture_file(submenu_recent_files);
1045 }
1046
1047 static void menu_open_recent_file_answered_cb(gpointer dialog _U_, gint btn, gpointer data _U_)
1048 {
1049     switch(btn) {
1050     case(ESD_BTN_YES):
1051         /* save file first */
1052         file_save_as_cmd(after_save_open_recent_file, data);
1053         break;
1054     case(ESD_BTN_NO):
1055         cf_close(&cfile);
1056         menu_open_recent_file_cmd(data);
1057         break;
1058     case(ESD_BTN_CANCEL):
1059         break;
1060     default:
1061         g_assert_not_reached();
1062     }
1063 }
1064
1065 void
1066 menu_open_recent_file_cmd_cb(GtkWidget *widget, gpointer data _U_) {
1067   gpointer  dialog;
1068
1069
1070   if((cfile.state != FILE_CLOSED) && !cfile.user_saved && prefs.gui_ask_unsaved) {
1071     /* user didn't saved his current file, ask him */
1072     dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_YES_NO_CANCEL,
1073                 PRIMARY_TEXT_START "Save capture file before opening a new one?" PRIMARY_TEXT_END "\n\n"
1074                 "If you open a new capture file without saving, your current capture data will be discarded.");
1075     simple_dialog_set_cb(dialog, menu_open_recent_file_answered_cb, widget);
1076   } else {
1077     /* unchanged file */
1078     menu_open_recent_file_cmd(widget);
1079   }
1080 }
1081
1082 /* add the capture filename (with an absolute path) to the "Recent Files" menu */
1083 void
1084 add_menu_recent_capture_file_absolute(gchar *cf_name) {
1085         GtkWidget *submenu_recent_files;
1086         GList *menu_item_list;
1087         GList *li;
1088         gchar *widget_cf_name;
1089         gchar *normalized_cf_name;
1090         GtkWidget *menu_item;
1091         guint cnt;
1092
1093
1094
1095         normalized_cf_name = g_strdup(cf_name);
1096 #ifdef _WIN32
1097         /* replace all slashes by backslashes */
1098         g_strdelimit(normalized_cf_name, "/", '\\');
1099 #endif
1100
1101         /* get the submenu container item */
1102         submenu_recent_files = gtk_item_factory_get_widget(main_menu_factory, MENU_RECENT_FILES_PATH);
1103
1104         /* convert container to a GList */
1105         menu_item_list = gtk_container_children(GTK_CONTAINER(submenu_recent_files));
1106
1107         /* iterate through list items of menu_item_list, 
1108          * removing special items, a maybe duplicate entry and every item above count_max */
1109         cnt = 1;
1110         for (li = g_list_first(menu_item_list); li; li = li->next, cnt++) {
1111                 /* get capture filename */
1112                 menu_item = GTK_WIDGET(li->data);
1113                 widget_cf_name = OBJECT_GET_DATA(menu_item, MENU_RECENT_FILES_KEY);
1114
1115                 /* if this element string is one of our special items (seperator, ...) or
1116                  * already in the list or 
1117                  * this element is above maximum count (too old), remove it */
1118                 if (!widget_cf_name ||
1119 #ifdef _WIN32
1120                     /* do a case insensitive compare on win32 */
1121 #if GLIB_MAJOR_VERSION < 2
1122                     g_strncasecmp(widget_cf_name, normalized_cf_name, 1000) == 0 ||
1123 #else
1124                     g_ascii_strncasecmp(widget_cf_name, normalized_cf_name, 1000) == 0 ||
1125 #endif
1126 #else   /* _WIN32 */
1127                     /* do a case sensitive compare on unix */
1128                     strncmp(widget_cf_name, normalized_cf_name, 1000) == 0 ||
1129 #endif
1130                     cnt >= prefs.gui_recent_files_count_max) {
1131                         remove_menu_recent_capture_file(li->data, NULL);
1132                         cnt--;
1133                 }
1134         }
1135
1136         g_list_free(menu_item_list);
1137
1138         /* add new item at latest position */
1139         menu_item = gtk_menu_item_new_with_label(normalized_cf_name);
1140         OBJECT_SET_DATA(menu_item, MENU_RECENT_FILES_KEY, normalized_cf_name);
1141         gtk_menu_prepend (GTK_MENU(submenu_recent_files), menu_item);
1142         SIGNAL_CONNECT_OBJECT(GTK_OBJECT(menu_item), "activate", 
1143                 menu_open_recent_file_cmd_cb, (GtkObject *) menu_item);
1144         gtk_widget_show (menu_item);
1145
1146         /* add seperator at last position */
1147         menu_item = gtk_menu_item_new();
1148         gtk_menu_append (GTK_MENU(submenu_recent_files), menu_item);
1149         gtk_widget_show (menu_item);
1150
1151         /* add new "clear list" item at last position */
1152 #if GTK_MAJOR_VERSION < 2
1153         menu_item = gtk_menu_item_new_with_label("<Clear File List>");
1154 #else
1155         menu_item = gtk_image_menu_item_new_from_stock(GTK_STOCK_CLEAR, NULL);
1156 #endif
1157         gtk_menu_append (GTK_MENU(submenu_recent_files), menu_item);
1158         SIGNAL_CONNECT_OBJECT(GTK_OBJECT(menu_item), "activate", 
1159                 clear_menu_recent_capture_file_cmd_cb, (GtkObject *) menu_item);
1160         gtk_widget_show (menu_item);
1161
1162         update_menu_recent_capture_file(submenu_recent_files);
1163 }
1164
1165
1166 /* add the capture filename to the "Recent Files" menu */
1167 /* (will change nothing, if this filename is already in the menu) */
1168 void
1169 add_menu_recent_capture_file(gchar *cf_name) {
1170         gchar *curr;
1171         gchar *absolute;
1172         
1173         
1174         /* if this filename is an absolute path, we can use it directly */
1175         if (g_path_is_absolute(cf_name)) {
1176                 add_menu_recent_capture_file_absolute(cf_name);
1177                 return;
1178         }
1179
1180         /* this filename is not an absolute path, prepend the current dir */
1181         curr = g_get_current_dir();
1182         absolute = g_strdup_printf("%s%s%s", curr, G_DIR_SEPARATOR_S, cf_name);
1183         add_menu_recent_capture_file_absolute(absolute);
1184         g_free(curr);
1185         g_free(absolute);
1186 }
1187
1188
1189 /* write all capture filenames of the menu to the user's recent file */
1190 void
1191 menu_recent_file_write_all(FILE *rf) {
1192     GtkWidget   *submenu_recent_files;
1193     GList       *children;
1194     GList       *child;
1195     gchar       *cf_name;
1196
1197
1198     submenu_recent_files = gtk_item_factory_get_widget(main_menu_factory, MENU_RECENT_FILES_PATH);
1199
1200     /* we have to iterate backwards through the children's list,
1201      * so we get the latest item last in the file.
1202      * (don't use gtk_container_foreach() here, it will return the wrong iteration order) */
1203     children = gtk_container_children(GTK_CONTAINER(submenu_recent_files));
1204     child = g_list_last(children);
1205     while(child != NULL) {
1206         /* get capture filename from the menu item label */
1207         cf_name = OBJECT_GET_DATA(child->data, MENU_RECENT_FILES_KEY);
1208         if (cf_name) {
1209             fprintf (rf, RECENT_KEY_CAPTURE_FILE ": %s\n", cf_name);
1210         }
1211
1212         child = g_list_previous(child);
1213     }
1214
1215     g_list_free(children);
1216 }
1217
1218
1219 static void
1220 main_toolbar_show_cb(GtkWidget *w _U_, gpointer d _U_)
1221 {
1222
1223     /* save current setting in recent */
1224     recent.main_toolbar_show = GTK_CHECK_MENU_ITEM(w)->active;
1225
1226     main_widgets_show_or_hide();
1227 }
1228
1229
1230 static void
1231 filter_toolbar_show_cb(GtkWidget *w _U_, gpointer d _U_)
1232 {
1233
1234     /* save current setting in recent */
1235     recent.filter_toolbar_show = GTK_CHECK_MENU_ITEM(w)->active;
1236
1237     main_widgets_show_or_hide();
1238 }
1239
1240
1241 static void
1242 packet_list_show_cb(GtkWidget *w _U_, gpointer d _U_)
1243 {
1244
1245     /* save current setting in recent */
1246     recent.packet_list_show = GTK_CHECK_MENU_ITEM(w)->active;
1247
1248     main_widgets_show_or_hide();
1249 }
1250
1251
1252 static void
1253 tree_view_show_cb(GtkWidget *w _U_, gpointer d _U_)
1254 {
1255
1256     /* save current setting in recent */
1257     recent.tree_view_show = GTK_CHECK_MENU_ITEM(w)->active;
1258
1259     main_widgets_show_or_hide();
1260 }
1261
1262
1263 static void
1264 byte_view_show_cb(GtkWidget *w _U_, gpointer d _U_)
1265 {
1266
1267     /* save current setting in recent */
1268     recent.byte_view_show = GTK_CHECK_MENU_ITEM(w)->active;
1269
1270     main_widgets_show_or_hide();
1271 }
1272
1273
1274 static void
1275 statusbar_show_cb(GtkWidget *w _U_, gpointer d _U_)
1276 {
1277
1278     /* save current setting in recent */
1279     recent.statusbar_show = GTK_CHECK_MENU_ITEM(w)->active;
1280
1281     main_widgets_show_or_hide();
1282 }
1283
1284
1285 static void 
1286 timestamp_absolute_cb(GtkWidget *w _U_, gpointer d _U_)
1287 {
1288     if (recent.gui_time_format != TS_ABSOLUTE) {
1289         set_timestamp_setting(TS_ABSOLUTE);
1290         recent.gui_time_format  = TS_ABSOLUTE;
1291         cf_change_time_formats(&cfile);
1292     }
1293 }
1294
1295 static void 
1296 timestamp_absolute_date_cb(GtkWidget *w _U_, gpointer d _U_)
1297 {
1298     if (recent.gui_time_format != TS_ABSOLUTE_WITH_DATE) {
1299         set_timestamp_setting(TS_ABSOLUTE_WITH_DATE);
1300         recent.gui_time_format  = TS_ABSOLUTE_WITH_DATE;
1301         cf_change_time_formats(&cfile);
1302     }
1303 }
1304
1305 static void 
1306 timestamp_relative_cb(GtkWidget *w _U_, gpointer d _U_)
1307 {
1308     if (recent.gui_time_format != TS_RELATIVE) {
1309         set_timestamp_setting(TS_RELATIVE);
1310         recent.gui_time_format  = TS_RELATIVE;
1311         cf_change_time_formats(&cfile);
1312     }
1313 }
1314
1315 static void 
1316 timestamp_delta_cb(GtkWidget *w _U_, gpointer d _U_)
1317 {
1318     if (recent.gui_time_format != TS_DELTA) {
1319         set_timestamp_setting(TS_DELTA);
1320         recent.gui_time_format  = TS_DELTA;
1321         cf_change_time_formats(&cfile);
1322     }
1323 }
1324
1325 void
1326 menu_name_resolution_changed(void)
1327 {
1328     GtkWidget *menu = NULL;
1329
1330     menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Name Resolution/Enable for MAC Layer");
1331     gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), g_resolv_flags & RESOLV_MAC);
1332
1333     menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Name Resolution/Enable for Network Layer");
1334     gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), g_resolv_flags & RESOLV_NETWORK);
1335
1336     menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Name Resolution/Enable for Transport Layer");
1337     gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), g_resolv_flags & RESOLV_TRANSPORT);
1338 }
1339
1340 static void 
1341 name_resolution_mac_cb(GtkWidget *w _U_, gpointer d _U_)
1342 {
1343     if (GTK_CHECK_MENU_ITEM(w)->active) {
1344         g_resolv_flags |= RESOLV_MAC;
1345     } else {
1346         g_resolv_flags &= ~RESOLV_MAC;
1347     }
1348 }
1349
1350 static void 
1351 name_resolution_network_cb(GtkWidget *w _U_, gpointer d _U_)
1352 {
1353     if (GTK_CHECK_MENU_ITEM(w)->active) {
1354         g_resolv_flags |= RESOLV_NETWORK;
1355     } else {
1356         g_resolv_flags &= ~RESOLV_NETWORK;
1357     }
1358 }
1359
1360 static void 
1361 name_resolution_transport_cb(GtkWidget *w _U_, gpointer d _U_)
1362 {
1363     if (GTK_CHECK_MENU_ITEM(w)->active) {
1364         g_resolv_flags |= RESOLV_TRANSPORT;
1365     } else {
1366         g_resolv_flags &= ~RESOLV_TRANSPORT;
1367     }
1368 }
1369
1370 #ifdef HAVE_LIBPCAP
1371 void
1372 menu_auto_scroll_live_changed(gboolean auto_scroll_live_in) {
1373     GtkWidget *menu;
1374
1375
1376     /* tell menu about it */
1377     menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Auto Scroll in Live Capture");
1378     if( ((gboolean) GTK_CHECK_MENU_ITEM(menu)->active) != auto_scroll_live_in) {
1379         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), auto_scroll_live_in);
1380     }
1381
1382     /* tell toolbar about it */
1383     toolbar_auto_scroll_live_changed(auto_scroll_live_in);
1384
1385     /* change auto scroll */
1386     if(auto_scroll_live_in != auto_scroll_live) {
1387         auto_scroll_live  = auto_scroll_live_in;
1388     }
1389 }
1390
1391 static void 
1392 auto_scroll_live_cb(GtkWidget *w _U_, gpointer d _U_)
1393 {
1394     menu_auto_scroll_live_changed(GTK_CHECK_MENU_ITEM(w)->active);
1395 }
1396 #endif
1397
1398
1399 void
1400 menu_colorize_changed(gboolean packet_list_colorize) {
1401     GtkWidget *menu;
1402
1403
1404     /* tell menu about it */
1405     menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Colorize Packet List");
1406     if( ((gboolean) GTK_CHECK_MENU_ITEM(menu)->active) != packet_list_colorize) {
1407         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), packet_list_colorize);
1408     }
1409
1410     /* tell toolbar about it */
1411     toolbar_colorize_changed(packet_list_colorize);
1412
1413     /* change colorization */
1414     if(packet_list_colorize != recent.packet_list_colorize) {
1415         recent.packet_list_colorize = packet_list_colorize;
1416         color_filters_enable(packet_list_colorize);
1417         cf_colorize_packets(&cfile);
1418     }
1419 }
1420
1421 static void 
1422 colorize_cb(GtkWidget *w, gpointer d _U_)
1423 {
1424     menu_colorize_changed(GTK_CHECK_MENU_ITEM(w)->active);
1425 }
1426
1427
1428 /* the recent file read has finished, update the menu corresponding */
1429 void
1430 menu_recent_read_finished(void) {
1431     GtkWidget *menu = NULL;
1432
1433     menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Main Toolbar");
1434     gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), recent.main_toolbar_show);
1435
1436     menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Filter Toolbar");
1437     gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), recent.filter_toolbar_show);
1438
1439     menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Statusbar");
1440     gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), recent.statusbar_show);
1441
1442     menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Packet List");
1443     gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), recent.packet_list_show);
1444
1445     menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Packet Details");
1446     gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), recent.tree_view_show);
1447
1448     menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Packet Bytes");
1449     gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), recent.byte_view_show);
1450
1451     menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Colorize Packet List");
1452     gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), recent.packet_list_colorize);
1453
1454     menu_name_resolution_changed();
1455
1456 #ifdef HAVE_LIBPCAP
1457     menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Auto Scroll in Live Capture");
1458     gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), auto_scroll_live);
1459 #endif
1460
1461     main_widgets_rearrange();
1462
1463     /* don't change the time format, if we had a command line value */
1464     if (get_timestamp_setting() != TS_NOT_SET) {
1465         recent.gui_time_format = get_timestamp_setting();
1466     }
1467
1468     switch(recent.gui_time_format) {
1469     case(TS_ABSOLUTE):
1470         menu = gtk_item_factory_get_widget(main_menu_factory, 
1471             "/View/Time Display Format/Time of Day");
1472         /* set_active will not trigger the callback when activating an active item! */
1473         recent.gui_time_format = -1;
1474         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), FALSE);
1475         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), TRUE);
1476         break;
1477     case(TS_ABSOLUTE_WITH_DATE):
1478         menu = gtk_item_factory_get_widget(main_menu_factory, 
1479             "/View/Time Display Format/Date and Time of Day");
1480         recent.gui_time_format = -1;
1481         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), TRUE);
1482         break;
1483     case(TS_RELATIVE):
1484         menu = gtk_item_factory_get_widget(main_menu_factory, 
1485             "/View/Time Display Format/Seconds Since Beginning of Capture");
1486         recent.gui_time_format = -1;
1487         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), TRUE);
1488         break;
1489     case(TS_DELTA):
1490         menu = gtk_item_factory_get_widget(main_menu_factory, 
1491             "/View/Time Display Format/Seconds Since Previous Packet");
1492         recent.gui_time_format = -1;
1493         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), TRUE);
1494         break;
1495     default:
1496         g_assert_not_reached();
1497     }
1498
1499     menu_colorize_changed(recent.packet_list_colorize);
1500 }
1501
1502
1503 gint
1504 popup_menu_handler(GtkWidget *widget, GdkEvent *event, gpointer data)
1505 {
1506     GtkWidget *menu = (GtkWidget *)data;
1507     GdkEventButton *event_button = NULL;
1508     gint row, column;
1509
1510     if(widget == NULL || event == NULL || data == NULL) {
1511         return FALSE;
1512     }
1513
1514     /*
1515      * If we ever want to make the menu differ based on what row
1516      * and/or column we're above, we'd use "eth_clist_get_selection_info()"
1517      * to find the row and column number for the coordinates; a CTree is,
1518      * I guess, like a CList with one column(?) and the expander widget
1519      * as a pixmap.
1520      */
1521     /* Check if we are on packet_list object */
1522     if (widget == OBJECT_GET_DATA(popup_menu_object, E_MPACKET_LIST_KEY)) {
1523         if (packet_list_get_event_row_column(widget, (GdkEventButton *)event,
1524                                              &row, &column)) {
1525             OBJECT_SET_DATA(popup_menu_object, E_MPACKET_LIST_ROW_KEY,
1526                             GINT_TO_POINTER(row));
1527             OBJECT_SET_DATA(popup_menu_object, E_MPACKET_LIST_COL_KEY,
1528                             GINT_TO_POINTER(column));
1529             packet_list_set_selected_row(row);
1530         }
1531     }
1532
1533     /* Check if we are on tree_view object */
1534     if (widget == tree_view) {
1535         tree_view_select(widget, (GdkEventButton *) event);
1536     }
1537
1538     /* Check if we are on byte_view object */
1539     if(widget == get_notebook_bv_ptr(byte_nb_ptr)) {
1540         byte_view_select(widget, (GdkEventButton *) event);
1541     }
1542
1543     /* context menu handler (but the byte view notebook pages have their own handler) */
1544     if(event->type == GDK_BUTTON_PRESS && widget != byte_nb_ptr) {
1545         event_button = (GdkEventButton *) event;
1546
1547         /* To qoute the "Gdk Event Structures" doc:
1548          * "Normally button 1 is the left mouse button, 2 is the middle button, and 3 is the right button" */
1549         if(event_button->button == 3) {
1550             gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL,
1551                            event_button->button,
1552                            event_button->time);
1553             SIGNAL_EMIT_STOP_BY_NAME(widget, "button_press_event");
1554             return TRUE;
1555         }
1556     }
1557 #if GTK_MAJOR_VERSION >= 2
1558     /* GDK_2BUTTON_PRESS is a doubleclick -> expand/collapse tree row */
1559     /* GTK version 1 seems to be doing this automatically */
1560     if (widget == tree_view && event->type == GDK_2BUTTON_PRESS) {
1561         GtkTreePath      *path;
1562
1563         if (gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(widget),
1564                                           (gint) (((GdkEventButton *)event)->x),
1565                                           (gint) (((GdkEventButton *)event)->y),
1566                                           &path, NULL, NULL, NULL))
1567         {
1568             if (gtk_tree_view_row_expanded(GTK_TREE_VIEW(widget), path))
1569                 gtk_tree_view_collapse_row(GTK_TREE_VIEW(widget), path);
1570             else
1571                 gtk_tree_view_expand_row(GTK_TREE_VIEW(widget), path,
1572                                          FALSE);
1573             gtk_tree_path_free(path);
1574         }
1575     }
1576 #endif
1577     return FALSE;
1578 }
1579
1580 /* Enable or disable menu items based on whether you have a capture file
1581    you've finished reading. */
1582 void
1583 set_menus_for_capture_file(gboolean have_capture_file)
1584 {
1585   set_menu_sensitivity(main_menu_factory, "/File/Open...", have_capture_file);
1586   set_menu_sensitivity(main_menu_factory, "/File/Open Recent", have_capture_file);
1587   set_menu_sensitivity(main_menu_factory, "/File/Merge...", have_capture_file);
1588   set_menu_sensitivity(main_menu_factory, "/File/Close", have_capture_file);
1589   set_menu_sensitivity(main_menu_factory, "/File/Save As...",
1590       have_capture_file);
1591   set_menu_sensitivity(main_menu_factory, "/File/Export", have_capture_file);
1592   set_menu_sensitivity(main_menu_factory, "/View/Reload", have_capture_file);
1593   set_toolbar_for_capture_file(have_capture_file);
1594   packets_bar_update();
1595 }
1596
1597 /* Enable or disable menu items based on whether you have an unsaved
1598    capture file you've finished reading. */
1599 void
1600 set_menus_for_unsaved_capture_file(gboolean have_unsaved_capture_file)
1601 {
1602   set_menu_sensitivity(main_menu_factory, "/File/Save",
1603       have_unsaved_capture_file);
1604   set_toolbar_for_unsaved_capture_file(have_unsaved_capture_file);
1605 }
1606
1607 /* Enable or disable menu items based on whether there's a capture in
1608    progress. */
1609 void
1610 set_menus_for_capture_in_progress(gboolean capture_in_progress)
1611 {
1612   set_menu_sensitivity(main_menu_factory, "/File/Open...",
1613       !capture_in_progress);
1614   set_menu_sensitivity(main_menu_factory, "/File/Open Recent", 
1615       !capture_in_progress);
1616 #ifdef HAVE_LIBPCAP
1617   set_menu_sensitivity(main_menu_factory, "/Capture/Options...",
1618       !capture_in_progress);
1619   set_menu_sensitivity(main_menu_factory, "/Capture/Start",
1620       !capture_in_progress);
1621   set_menu_sensitivity(main_menu_factory, "/Capture/Stop",
1622       capture_in_progress);
1623   set_menu_sensitivity(main_menu_factory, "/Capture/Restart",
1624       capture_in_progress);
1625   set_toolbar_for_capture_in_progress(capture_in_progress);
1626
1627   set_capture_if_dialog_for_capture_in_progress(capture_in_progress);
1628 #endif /* HAVE_LIBPCAP */
1629 }
1630
1631 /* Enable or disable menu items based on whether you have some captured
1632    packets. */
1633 static gboolean
1634 walk_menu_tree_for_captured_packets(GList *node,
1635     gboolean have_captured_packets)
1636 {
1637         gboolean    is_enabled;
1638         GList       *child;
1639         menu_item_t *node_data = node->data;
1640
1641         /*
1642          * Is this a leaf node or an interior node?
1643          */
1644         if (node_data->children == NULL) {
1645                 /*
1646                  * It's a leaf node.
1647                  *
1648                  * If it has no "selected_packet_enabled()" or
1649                  * "selected_tree_row_enabled()" routines, we enable
1650                  * it.  This allows tap windows to be popped up even
1651                  * if you have no capture file; this is done to let
1652                  * the user pop up multiple tap windows before reading
1653                  * in a capture file, so that they can be processed in
1654                  * parallel while the capture file is being read rather
1655                  * than one at at time as you pop up the windows, and to
1656                  * let the user pop up tap windows before starting an
1657                  * "Update list of packets in real time" capture, so that
1658                  * the statistics can be displayed while the capture is
1659                  * in progress.
1660                  *
1661                  * If it has either of those routines, we disable it for
1662                  * now - as long as, when a capture is first available,
1663                  * we don't get called after a packet or tree row is
1664                  * selected, that's OK.
1665                  * XXX - that should be done better.
1666                  */
1667                 if (node_data->selected_packet_enabled == NULL &&
1668                     node_data->selected_tree_row_enabled == NULL)
1669                         node_data->enabled = TRUE;
1670                 else
1671                         node_data->enabled = FALSE;
1672         } else {
1673                 /*
1674                  * It's an interior node; call
1675                  * "walk_menu_tree_for_captured_packets()" on all its
1676                  * children and, if any of them are enabled, enable
1677                  * this node, otherwise disable it.
1678                  *
1679                  * XXX - should we just leave all interior nodes enabled?
1680                  * Which is a better UI choice?
1681                  */
1682                 is_enabled = FALSE;
1683                 for (child = node_data->children; child != NULL; child =
1684                     child->next) {
1685                         if (walk_menu_tree_for_captured_packets(child,
1686                             have_captured_packets))
1687                                 is_enabled = TRUE;
1688                 }
1689                 node_data->enabled = is_enabled;
1690         }
1691
1692         /*
1693          * The root node doesn't correspond to a menu tree item; it
1694          * has a null name pointer.
1695          */
1696         if (node_data->name != NULL) {
1697                 set_menu_sensitivity(main_menu_factory, node_data->name,
1698                     node_data->enabled);
1699         }
1700         return node_data->enabled;
1701 }
1702
1703 void
1704 set_menus_for_captured_packets(gboolean have_captured_packets)
1705 {
1706   set_menu_sensitivity(main_menu_factory, "/File/Print...",
1707       have_captured_packets);
1708   set_menu_sensitivity(packet_list_menu_factory, "/Print...",
1709       have_captured_packets);
1710   set_menu_sensitivity(main_menu_factory, "/Edit/Find Packet...",
1711       have_captured_packets);
1712   set_menu_sensitivity(main_menu_factory, "/Edit/Find Next",
1713       have_captured_packets);
1714   set_menu_sensitivity(main_menu_factory, "/Edit/Find Previous",
1715       have_captured_packets);
1716   set_menu_sensitivity(main_menu_factory, "/View/Zoom In",
1717       have_captured_packets);
1718   set_menu_sensitivity(main_menu_factory, "/View/Zoom Out",
1719       have_captured_packets);
1720   set_menu_sensitivity(main_menu_factory, "/View/Normal Size",
1721       have_captured_packets);
1722   set_menu_sensitivity(main_menu_factory, "/Go/Go to Packet...",
1723       have_captured_packets);
1724   set_menu_sensitivity(main_menu_factory, "/Go/First Packet",
1725       have_captured_packets);
1726   set_menu_sensitivity(main_menu_factory, "/Go/Last Packet",
1727       have_captured_packets);
1728   set_menu_sensitivity(main_menu_factory, "/Statistics/Summary",
1729       have_captured_packets);
1730   set_menu_sensitivity(main_menu_factory, "/Statistics/Protocol Hierarchy", 
1731       have_captured_packets);
1732       
1733   walk_menu_tree_for_captured_packets(tap_menu_tree_root,
1734       have_captured_packets);
1735   set_toolbar_for_captured_packets(have_captured_packets);
1736   packets_bar_update();
1737 }
1738
1739 /* Enable or disable menu items based on whether a packet is selected and,
1740    if so, on the properties of the packet. */
1741 static gboolean
1742 walk_menu_tree_for_selected_packet(GList *node, frame_data *fd,
1743     epan_dissect_t *edt)
1744 {
1745         gboolean is_enabled;
1746         GList *child;
1747         menu_item_t *node_data = node->data;
1748
1749         /*
1750          * Is this a leaf node or an interior node?
1751          */
1752         if (node_data->children == NULL) {
1753                 /*
1754                  * It's a leaf node.
1755                  *
1756                  * If it has no "selected_packet_enabled()" routine,
1757                  * leave its enabled/disabled status alone - it
1758                  * doesn't depend on whether we have a packet selected
1759                  * or not or on the selected packet.
1760                  *
1761                  * If it has a "selected_packet_enabled()" routine,
1762                  * call it and set the item's enabled/disabled status
1763                  * based on its return value.
1764                  */
1765                 if (node_data->selected_packet_enabled != NULL)
1766                         node_data->enabled = node_data->selected_packet_enabled(fd, edt);
1767         } else {
1768                 /*
1769                  * It's an interior node; call
1770                  * "walk_menu_tree_for_selected_packet()" on all its
1771                  * children and, if any of them are enabled, enable
1772                  * this node, otherwise disable it.
1773                  *
1774                  * XXX - should we just leave all interior nodes enabled?
1775                  * Which is a better UI choice?
1776                  */
1777                 is_enabled = FALSE;
1778                 for (child = node_data->children; child != NULL; child =
1779                     child->next) {
1780                         if (walk_menu_tree_for_selected_packet(child, fd, edt))
1781                                 is_enabled = TRUE;
1782                 }
1783                 node_data->enabled = is_enabled;
1784         }
1785
1786         /*
1787          * The root node doesn't correspond to a menu tree item; it
1788          * has a null name pointer.
1789          */
1790         if (node_data->name != NULL) {
1791                 set_menu_sensitivity(main_menu_factory, node_data->name,
1792                     node_data->enabled);
1793         }
1794         return node_data->enabled;
1795 }
1796
1797 void
1798 set_menus_for_selected_packet(capture_file *cf)
1799 {
1800   set_menu_sensitivity(main_menu_factory, "/Edit/Mark Packet (toggle)",
1801       cf->current_frame != NULL);
1802   set_menu_sensitivity(packet_list_menu_factory, "/Mark Packet (toggle)",
1803       cf->current_frame != NULL);
1804   set_menu_sensitivity(main_menu_factory, "/Edit/Time Reference",
1805       cf->current_frame != NULL);
1806   set_menu_sensitivity(packet_list_menu_factory, "/Time Reference",
1807       cf->current_frame != NULL);
1808   set_menu_sensitivity(main_menu_factory, "/Edit/Mark All Packets",
1809       cf->current_frame != NULL);
1810   set_menu_sensitivity(main_menu_factory, "/Edit/Unmark All Packets",
1811       cf->current_frame != NULL);
1812   set_menu_sensitivity(main_menu_factory, "/View/Resize All Columns",
1813       cf->current_frame != NULL);
1814   set_menu_sensitivity(main_menu_factory, "/View/Collapse All",
1815       cf->current_frame != NULL);
1816   set_menu_sensitivity(tree_view_menu_factory, "/Collapse All",
1817       cf->current_frame != NULL);
1818   set_menu_sensitivity(main_menu_factory, "/View/Expand All",
1819       cf->current_frame != NULL);
1820   set_menu_sensitivity(tree_view_menu_factory, "/Expand All",
1821       cf->current_frame != NULL);
1822   set_menu_sensitivity(main_menu_factory, "/View/Show Packet in New Window",
1823       cf->current_frame != NULL);
1824   set_menu_sensitivity(packet_list_menu_factory, "/Show Packet in New Window",
1825       cf->current_frame != NULL);
1826   set_menu_sensitivity(main_menu_factory, "/Analyze/Follow TCP Stream",
1827       cf->current_frame != NULL ? (cf->edt->pi.ipproto == IP_PROTO_TCP) : FALSE);
1828   set_menu_sensitivity(packet_list_menu_factory, "/Follow TCP Stream",
1829       cf->current_frame != NULL ? (cf->edt->pi.ipproto == IP_PROTO_TCP) : FALSE);
1830   set_menu_sensitivity(tree_view_menu_factory, "/Follow TCP Stream",
1831       cf->current_frame != NULL ? (cf->edt->pi.ipproto == IP_PROTO_TCP) : FALSE);
1832   set_menu_sensitivity(main_menu_factory, "/Analyze/Decode As...",
1833       cf->current_frame != NULL && decode_as_ok());
1834   set_menu_sensitivity(packet_list_menu_factory, "/Decode As...",
1835       cf->current_frame != NULL && decode_as_ok());
1836   set_menu_sensitivity(tree_view_menu_factory, "/Decode As...",
1837       cf->current_frame != NULL && decode_as_ok());
1838   set_menu_sensitivity(main_menu_factory, "/View/Name Resolution/Resolve Name",
1839       cf->current_frame != NULL && (g_resolv_flags & RESOLV_ALL_ADDRS) != RESOLV_ALL_ADDRS);
1840   set_menu_sensitivity(tree_view_menu_factory, "/Resolve Name",
1841       cf->current_frame != NULL && (g_resolv_flags & RESOLV_ALL_ADDRS) != RESOLV_ALL_ADDRS);
1842   set_menu_sensitivity(packet_list_menu_factory, "/Apply as Filter",
1843       cf->current_frame != NULL);
1844   set_menu_sensitivity(packet_list_menu_factory, "/Prepare a Filter",
1845       cf->current_frame != NULL);
1846
1847   walk_menu_tree_for_selected_packet(tap_menu_tree_root, cf->current_frame,
1848       cf->edt);
1849   packets_bar_update();
1850 }
1851
1852 /* Enable or disable menu items based on whether a tree row is selected
1853    and, if so, on the properties of the tree row. */
1854 static gboolean
1855 walk_menu_tree_for_selected_tree_row(GList *node, field_info *fi)
1856 {
1857         gboolean is_enabled;
1858         GList *child;
1859         menu_item_t *node_data = node->data;
1860
1861         /*
1862          * Is this a leaf node or an interior node?
1863          */
1864         if (node_data->children == NULL) {
1865                 /*
1866                  * It's a leaf node.
1867                  *
1868                  * If it has no "selected_tree_row_enabled()" routine,
1869                  * leave its enabled/disabled status alone - it
1870                  * doesn't depend on whether we have a tree row selected
1871                  * or not or on the selected tree row.
1872                  *
1873                  * If it has a "selected_tree_row_enabled()" routine,
1874                  * call it and set the item's enabled/disabled status
1875                  * based on its return value.
1876                  */
1877                 if (node_data->selected_tree_row_enabled != NULL)
1878                         node_data->enabled = node_data->selected_tree_row_enabled(fi);
1879         } else {
1880                 /*
1881                  * It's an interior node; call
1882                  * "walk_menu_tree_for_selected_tree_row()" on all its
1883                  * children and, if any of them are enabled, enable
1884                  * this node, otherwise disable it.
1885                  *
1886                  * XXX - should we just leave all interior nodes enabled?
1887                  * Which is a better UI choice?
1888                  */
1889                 is_enabled = FALSE;
1890                 for (child = node_data->children; child != NULL; child =
1891                     child->next) {
1892                         if (walk_menu_tree_for_selected_tree_row(child, fi))
1893                                 is_enabled = TRUE;
1894                 }
1895                 node_data->enabled = is_enabled;
1896         }
1897
1898         /*
1899          * The root node doesn't correspond to a menu tree item; it
1900          * has a null name pointer.
1901          */
1902         if (node_data->name != NULL) {
1903                 set_menu_sensitivity(main_menu_factory, node_data->name,
1904                     node_data->enabled);
1905         }
1906         return node_data->enabled;
1907 }
1908
1909 void
1910 set_menus_for_selected_tree_row(capture_file *cf)
1911 {
1912   gboolean properties;
1913
1914
1915   set_menu_sensitivity(main_menu_factory, "/File/Export/Selected Packet Bytes...", 
1916       cf->finfo_selected != NULL);  
1917   set_menu_sensitivity(hexdump_menu_factory, "/Copy", 
1918       cf->finfo_selected != NULL);
1919   set_menu_sensitivity(hexdump_menu_factory, "/Export Selected Packet Bytes...", 
1920       cf->finfo_selected != NULL);
1921   
1922   if (cf->finfo_selected != NULL) {
1923         header_field_info *hfinfo = cf->finfo_selected->hfinfo;
1924         if (hfinfo->parent == -1) {
1925           properties = prefs_is_registered_protocol(hfinfo->abbrev);
1926         } else {
1927           properties = prefs_is_registered_protocol(proto_registrar_get_abbrev(hfinfo->parent));
1928         }
1929         set_menu_sensitivity(main_menu_factory,
1930           "/Go/Go to Corresponding Packet", hfinfo->type == FT_FRAMENUM);
1931         set_menu_sensitivity(tree_view_menu_factory,
1932           "/Go to Corresponding Packet", hfinfo->type == FT_FRAMENUM);
1933         set_menu_sensitivity(main_menu_factory, "/Analyze/Apply as Filter",
1934           proto_can_match_selected(cf->finfo_selected, cf->edt));
1935         set_menu_sensitivity(tree_view_menu_factory, "/Apply as Filter",
1936           proto_can_match_selected(cf->finfo_selected, cf->edt));
1937         set_menu_sensitivity(main_menu_factory, "/Analyze/Prepare a Filter",
1938           proto_can_match_selected(cf->finfo_selected, cf->edt));
1939         set_menu_sensitivity(tree_view_menu_factory, "/Prepare a Filter",
1940           proto_can_match_selected(cf->finfo_selected, cf->edt));
1941         set_menu_sensitivity(tree_view_menu_factory, "/Protocol Preferences...",
1942           properties);
1943         set_menu_sensitivity(main_menu_factory, "/View/Expand Tree", cf->finfo_selected->tree_type != -1);
1944         set_menu_sensitivity(tree_view_menu_factory, "/Wiki Protocol Page",
1945           TRUE);
1946         set_menu_sensitivity(tree_view_menu_factory, "/Filter Field Reference",
1947           TRUE);
1948   } else {
1949         set_menu_sensitivity(main_menu_factory,
1950             "/Go/Go to Corresponding Packet", FALSE);
1951         set_menu_sensitivity(tree_view_menu_factory,
1952             "/Go to Corresponding Packet", FALSE);
1953         set_menu_sensitivity(main_menu_factory, "/Analyze/Apply as Filter", FALSE);
1954         set_menu_sensitivity(tree_view_menu_factory, "/Apply as Filter", FALSE);
1955         set_menu_sensitivity(main_menu_factory, "/Analyze/Prepare a Filter", FALSE);
1956         set_menu_sensitivity(tree_view_menu_factory, "/Prepare a Filter", FALSE);
1957         set_menu_sensitivity(tree_view_menu_factory, "/Protocol Preferences...",
1958           FALSE);
1959         set_menu_sensitivity(main_menu_factory, "/View/Expand Tree", FALSE);
1960         set_menu_sensitivity(tree_view_menu_factory, "/Wiki Protocol Page",
1961           FALSE);
1962         set_menu_sensitivity(tree_view_menu_factory, "/Filter Field Reference",
1963           FALSE);
1964   }
1965
1966   walk_menu_tree_for_selected_tree_row(tap_menu_tree_root, cf->finfo_selected);
1967 }
1968
1969 void set_menus_for_packet_history(gboolean back_history, gboolean forward_history) {
1970
1971   set_menu_sensitivity(main_menu_factory, "/Go/Back", back_history);
1972   set_menu_sensitivity(main_menu_factory, "/Go/Forward", forward_history);
1973
1974   set_toolbar_for_packet_history(back_history, forward_history);
1975 }
1976