6 * Ethereal - Network traffic analyzer
7 * By Gerald Combs <gerald@ethereal.com>
8 * Copyright 1998 Gerald Combs
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.
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.
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.
36 #include <epan/packet.h>
37 #include <epan/addr_resolv.h>
39 #include "about_dlg.h"
40 #include "capture_dlg.h"
41 #include "color_dlg.h"
42 #include "filter_dlg.h"
43 #include "dlg_utils.h"
47 #include "summary_dlg.h"
48 #include "prefs_dlg.h"
49 #include "packet_win.h"
51 #include "follow_dlg.h"
52 #include "decode_as_dlg.h"
54 #include "supported_protos_dlg.h"
55 #include "proto_dlg.h"
56 #include "proto_hier_stats_dlg.h"
58 #include <epan/plugins.h>
59 #include <epan/epan_dissect.h>
60 #include "compat_macros.h"
62 #include "gtkglobals.h"
66 #include "../ipproto.h"
67 #include "packet_list.h"
70 #include "../ui_util.h"
71 #include "proto_draw.h"
72 #include "conversations_table.h"
73 #include "hostlist_table.h"
74 #include "simple_dialog.h"
75 #include <epan/timestamp.h>
77 GtkWidget *popup_menu_object;
80 clear_menu_recent_capture_file_cmd_cb(GtkWidget *w, gpointer unused _U_);
82 typedef struct _menu_item {
86 GtkItemFactoryCallback callback;
87 gpointer callback_data;
88 gboolean (*selected_packet_enabled)(frame_data *, epan_dissect_t *);
89 gboolean (*selected_tree_row_enabled)(field_info *);
93 static GList *tap_menu_tree_root = NULL;
96 merge_all_tap_menus(GList *node);
98 #define GTK_MENU_FUNC(a) ((GtkItemFactoryCallback)(a))
100 static void menus_init(void);
101 static void set_menu_sensitivity (GtkItemFactory *, const gchar *, gint);
102 static void main_toolbar_show_cb(GtkWidget *w _U_, gpointer d _U_);
103 static void filter_toolbar_show_cb(GtkWidget *w _U_, gpointer d _U_);
104 static void packet_list_show_cb(GtkWidget *w _U_, gpointer d _U_);
105 static void tree_view_show_cb(GtkWidget *w _U_, gpointer d _U_);
106 static void byte_view_show_cb(GtkWidget *w _U_, gpointer d _U_);
107 static void statusbar_show_cb(GtkWidget *w _U_, gpointer d _U_);
108 static void timestamp_absolute_cb(GtkWidget *w _U_, gpointer d _U_);
109 static void timestamp_absolute_date_cb(GtkWidget *w _U_, gpointer d _U_);
110 static void timestamp_relative_cb(GtkWidget *w _U_, gpointer d _U_);
111 static void timestamp_delta_cb(GtkWidget *w _U_, gpointer d _U_);
112 static void name_resolution_mac_cb(GtkWidget *w _U_, gpointer d _U_);
113 static void name_resolution_network_cb(GtkWidget *w _U_, gpointer d _U_);
114 static void name_resolution_transport_cb(GtkWidget *w _U_, gpointer d _U_);
116 static void auto_scroll_live_cb(GtkWidget *w _U_, gpointer d _U_);
119 /* This is the GtkItemFactoryEntry structure used to generate new menus.
120 Item 1: The menu path. The letter after the underscore indicates an
121 accelerator key once the menu is open.
122 Item 2: The accelerator key for the entry
123 Item 3: The callback function.
124 Item 4: The callback action. This changes the parameters with
125 which the function is called. The default is 0.
126 Item 5: The item type, used to define what kind of an item it is.
127 Here are the possible values:
131 "<Title>" -> create a title item
132 "<Item>" -> create a simple item
133 "<ImageItem>" -> create an item holding an image (gtk2)
134 "<StockItem>" -> create an item holding a stock image (gtk2)
135 "<CheckItem>" -> create a check item
136 "<ToggleItem>" -> create a toggle item
137 "<RadioItem>" -> create a radio item
138 <path> -> path of a radio item to link against
139 "<Separator>" -> create a separator
140 "<Tearoff>" -> create a tearoff separator (gtk2)
141 "<Branch>" -> create an item to hold sub items (optional)
142 "<LastBranch>" -> create a right justified branch
143 Item 6: extra data needed for ImageItem and StockItem (gtk2)
146 /* As a general GUI guideline, we try to follow the Gnome Human Interface Guidelines, which can be found at:
147 http://developer.gnome.org/projects/gup/hig/1.0/index.html
149 Please note: there are some differences between the Gnome HIG menu suggestions and our implementation:
151 File/Open Recent: the Gnome HIG suggests putting the list of recently used files as elements into the File menuitem.
152 As this is ok for only a few items, this will become unhandy for 10 or even more list entries.
153 For this reason, we use a submenu for this.
155 File/Close: the Gnome HIG suggests putting this item just above the Quit item.
156 This results in unintuitive behaviour as both Close and Quit items are very near together.
157 By putting the Close item near the open item(s), it better suggests that it will close the
158 currently opened/captured file only.
163 static GtkItemFactoryEntry menu_items[] =
165 ITEM_FACTORY_ENTRY("/_File", NULL, NULL, 0, "<Branch>", NULL),
166 ITEM_FACTORY_STOCK_ENTRY("/File/_Open...", "<control>O", file_open_cmd_cb,
168 ITEM_FACTORY_ENTRY("/File/Open _Recent", NULL, NULL, 0, "<Branch>", NULL),
169 ITEM_FACTORY_ENTRY("/File/_Merge...", NULL, file_merge_cmd_cb, 0, NULL, NULL),
170 ITEM_FACTORY_STOCK_ENTRY("/File/_Close", "<control>W", file_close_cmd_cb,
172 ITEM_FACTORY_ENTRY("/File/<separator>", NULL, NULL, 0, "<Separator>", NULL),
173 ITEM_FACTORY_STOCK_ENTRY("/File/_Save", "<control>S", file_save_cmd_cb,
175 ITEM_FACTORY_STOCK_ENTRY("/File/Save _As...", "<shift><control>S", file_save_as_cmd_cb,
176 0, GTK_STOCK_SAVE_AS),
177 ITEM_FACTORY_ENTRY("/File/<separator>", NULL, NULL, 0, "<Separator>", NULL),
178 ITEM_FACTORY_ENTRY("/File/_Export", NULL, NULL, 0, "<Branch>", NULL),
179 ITEM_FACTORY_ENTRY("/File/Export/as \"Plain _Text\" file...", NULL, export_text_cmd_cb,
181 ITEM_FACTORY_ENTRY("/File/Export/as \"_PostScript\" file...", NULL, export_ps_cmd_cb,
183 ITEM_FACTORY_ENTRY("/File/Export/as XML - \"P_SML\" (packet summary) file...", NULL, export_psml_cmd_cb,
185 ITEM_FACTORY_ENTRY("/File/Export/as XML - \"P_DML\" (packet details) file...", NULL, export_pdml_cmd_cb,
187 ITEM_FACTORY_ENTRY("/File/Export/<separator>", NULL, NULL, 0, "<Separator>", NULL),
188 ITEM_FACTORY_ENTRY("/File/Export/Selected Packet _Bytes...", "<control>H", savehex_cb,
190 ITEM_FACTORY_ENTRY("/File/<separator>", NULL, NULL, 0, "<Separator>", NULL),
191 ITEM_FACTORY_STOCK_ENTRY("/File/_Print...", "<control>P", file_print_cmd_cb,
193 ITEM_FACTORY_ENTRY("/File/<separator>", NULL, NULL, 0, "<Separator>", NULL),
194 ITEM_FACTORY_STOCK_ENTRY("/File/_Quit", "<control>Q", file_quit_cmd_cb,
196 ITEM_FACTORY_ENTRY("/_Edit", NULL, NULL, 0, "<Branch>", NULL),
198 /* Un-#if this when we actually implement Cut/Copy/Paste. */
199 ITEM_FACTORY_STOCK_ENTRY("/Edit/Cut", "<control>X", NULL,
201 ITEM_FACTORY_STOCK_ENTRY("/Edit/Copy", "<control>C", NULL,
203 ITEM_FACTORY_STOCK_ENTRY("/Edit/Paste", "<control>V", NULL,
205 ITEM_FACTORY_ENTRY("/Edit/<separator>", NULL, NULL, 0, "<Separator>"),
207 ITEM_FACTORY_STOCK_ENTRY("/Edit/_Find Packet...", "<control>F",
208 find_frame_cb, 0, GTK_STOCK_FIND),
209 ITEM_FACTORY_STOCK_ENTRY("/Edit/Find Ne_xt", "<control>N", find_next_cb,
210 0, GTK_STOCK_GO_FORWARD),
211 ITEM_FACTORY_STOCK_ENTRY("/Edit/Find Pre_vious", "<control>B",
212 find_previous_cb, 0, GTK_STOCK_GO_BACK),
213 ITEM_FACTORY_ENTRY("/Edit/<separator>", NULL, NULL, 0, "<Separator>", NULL),
214 ITEM_FACTORY_ENTRY("/Edit/_Time Reference", NULL, NULL, 0, "<Branch>", NULL),
215 ITEM_FACTORY_ENTRY("/Edit/Time Reference/Set Time Reference (toggle)", "<control>T", reftime_frame_cb, REFTIME_TOGGLE, NULL, NULL),
216 ITEM_FACTORY_ENTRY("/Edit/Time Reference/Find Next", NULL, reftime_frame_cb, REFTIME_FIND_NEXT, NULL, NULL),
217 ITEM_FACTORY_ENTRY("/Edit/Time Reference/Find Previous", NULL, reftime_frame_cb, REFTIME_FIND_PREV, NULL, NULL),
218 ITEM_FACTORY_ENTRY("/Edit/_Mark Packet", "<control>M", mark_frame_cb,
220 ITEM_FACTORY_ENTRY("/Edit/Mark _All Packets", NULL, mark_all_frames_cb,
222 ITEM_FACTORY_ENTRY("/Edit/_Unmark All Packets", NULL, unmark_all_frames_cb,
224 ITEM_FACTORY_ENTRY("/Edit/<separator>", NULL, NULL, 0, "<Separator>", NULL),
225 ITEM_FACTORY_STOCK_ENTRY("/Edit/_Preferences...", "<shift><control>P", prefs_cb,
226 0, GTK_STOCK_PREFERENCES),
227 ITEM_FACTORY_ENTRY("/_View", NULL, NULL, 0, "<Branch>", NULL),
228 ITEM_FACTORY_ENTRY("/View/_Main Toolbar", NULL, main_toolbar_show_cb, 0, "<CheckItem>", NULL),
229 ITEM_FACTORY_ENTRY("/View/_Filter Toolbar", NULL, filter_toolbar_show_cb, 0, "<CheckItem>", NULL),
230 ITEM_FACTORY_ENTRY("/View/_Statusbar", NULL, statusbar_show_cb, 0, "<CheckItem>", NULL),
231 ITEM_FACTORY_ENTRY("/View/<separator>", NULL, NULL, 0, "<Separator>", NULL),
232 ITEM_FACTORY_ENTRY("/View/Packet _List", NULL, packet_list_show_cb, 0, "<CheckItem>", NULL),
233 ITEM_FACTORY_ENTRY("/View/Packet _Details", NULL, tree_view_show_cb, 0, "<CheckItem>", NULL),
234 ITEM_FACTORY_ENTRY("/View/Packet _Bytes", NULL, byte_view_show_cb, 0, "<CheckItem>", NULL),
235 ITEM_FACTORY_ENTRY("/View/<separator>", NULL, NULL, 0, "<Separator>", NULL),
236 ITEM_FACTORY_ENTRY("/View/_Time Display Format", NULL, NULL, 0, "<Branch>", NULL),
237 ITEM_FACTORY_ENTRY("/View/Time Display Format/Time of Day", NULL, timestamp_absolute_cb,
238 0, "<RadioItem>", NULL),
239 ITEM_FACTORY_ENTRY("/View/Time Display Format/Date and Time of Day", NULL, timestamp_absolute_date_cb,
240 0, "/View/Time Display Format/Time of Day", NULL),
241 ITEM_FACTORY_ENTRY("/View/Time Display Format/Seconds Since Beginning of Capture", NULL, timestamp_relative_cb,
242 0, "/View/Time Display Format/Time of Day", NULL),
243 ITEM_FACTORY_ENTRY("/View/Time Display Format/Seconds Since Previous Packet", NULL, timestamp_delta_cb,
244 0, "/View/Time Display Format/Time of Day", NULL),
245 ITEM_FACTORY_ENTRY("/View/Name Resol_ution", NULL, NULL, 0, "<Branch>", NULL),
246 ITEM_FACTORY_ENTRY("/View/Name Resolution/_Resolve Name", NULL, resolve_name_cb, 0, NULL, NULL),
247 ITEM_FACTORY_ENTRY("/View/Name Resolution/<separator>", NULL, NULL, 0, "<Separator>", NULL),
248 ITEM_FACTORY_ENTRY("/View/Name Resolution/Enable for _MAC Layer", NULL, name_resolution_mac_cb, 0, "<CheckItem>", NULL),
249 ITEM_FACTORY_ENTRY("/View/Name Resolution/Enable for _Network Layer", NULL, name_resolution_network_cb, 0, "<CheckItem>", NULL),
250 ITEM_FACTORY_ENTRY("/View/Name Resolution/Enable for _Transport Layer", NULL, name_resolution_transport_cb, 0, "<CheckItem>", NULL),
252 ITEM_FACTORY_ENTRY("/View/Auto Scroll in Li_ve Capture", NULL, auto_scroll_live_cb, 0, "<CheckItem>", NULL),
254 ITEM_FACTORY_ENTRY("/View/<separator>", NULL, NULL, 0, "<Separator>", NULL),
255 ITEM_FACTORY_STOCK_ENTRY("/View/_Zoom In", "<control>plus", view_zoom_in_cb,
256 0, GTK_STOCK_ZOOM_IN),
257 ITEM_FACTORY_STOCK_ENTRY("/View/Zoom _Out", "<control>minus", view_zoom_out_cb,
258 0, GTK_STOCK_ZOOM_OUT),
259 ITEM_FACTORY_STOCK_ENTRY("/View/_Normal Size", "<control>equal", view_zoom_100_cb,
260 0, GTK_STOCK_ZOOM_100),
261 ITEM_FACTORY_ENTRY("/View/<separator>", NULL, NULL, 0, "<Separator>", NULL),
262 ITEM_FACTORY_ENTRY("/View/Collapse _All", NULL, collapse_all_cb,
264 ITEM_FACTORY_ENTRY("/View/_Expand All", NULL, expand_all_cb,
266 ITEM_FACTORY_ENTRY("/View/Expand Tree", NULL, expand_tree_cb, 0, NULL, NULL),
267 ITEM_FACTORY_ENTRY("/View/<separator>", NULL, NULL, 0, "<Separator>", NULL),
268 ITEM_FACTORY_STOCK_ENTRY("/View/_Coloring Rules...", NULL, color_display_cb,
269 0, GTK_STOCK_SELECT_COLOR),
270 ITEM_FACTORY_ENTRY("/View/<separator>", NULL, NULL, 0, "<Separator>", NULL),
271 ITEM_FACTORY_ENTRY("/View/Show Packet in New _Window", NULL,
272 new_window_cb, 0, NULL, NULL),
273 ITEM_FACTORY_STOCK_ENTRY("/View/_Reload", "<control>R", file_reload_cmd_cb,
274 0, GTK_STOCK_REFRESH),
275 ITEM_FACTORY_ENTRY("/_Go", NULL, NULL, 0, "<Branch>", NULL),
276 ITEM_FACTORY_STOCK_ENTRY("/Go/_Go to Packet...", "<control>G",
277 goto_frame_cb, 0, GTK_STOCK_JUMP_TO),
278 ITEM_FACTORY_ENTRY("/Go/Go to _Corresponding Packet", NULL, goto_framenum_cb,
280 ITEM_FACTORY_ENTRY("/Go/<separator>", NULL, NULL, 0, "<Separator>", NULL),
281 ITEM_FACTORY_STOCK_ENTRY("/Go/_First Packet", NULL,
282 goto_top_frame_cb, 0, GTK_STOCK_GOTO_TOP),
283 ITEM_FACTORY_STOCK_ENTRY("/Go/_Last Packet", NULL,
284 goto_bottom_frame_cb, 0, GTK_STOCK_GOTO_BOTTOM),
286 ITEM_FACTORY_ENTRY("/_Capture", NULL, NULL, 0, "<Branch>", NULL),
287 ITEM_FACTORY_STOCK_ENTRY("/Capture/_Start...", "<control>K",
288 capture_prep_cb, 0, ETHEREAL_STOCK_CAPTURE_START),
289 ITEM_FACTORY_STOCK_ENTRY("/Capture/S_top", "<control>E", capture_stop_cb,
291 ITEM_FACTORY_ENTRY("/Capture/_Interfaces...", NULL,
292 capture_if_cb, 0, NULL, NULL),
293 ITEM_FACTORY_STOCK_ENTRY("/Capture/_Capture Filters...", NULL, cfilter_dialog_cb,
294 0, ETHEREAL_STOCK_CAPTURE_FILTER),
295 #endif /* HAVE_LIBPCAP */
296 ITEM_FACTORY_ENTRY("/_Analyze", NULL, NULL, 0, "<Branch>", NULL),
297 ITEM_FACTORY_STOCK_ENTRY("/Analyze/_Display Filters...", NULL, dfilter_dialog_cb,
298 0, ETHEREAL_STOCK_DISPLAY_FILTER),
299 ITEM_FACTORY_ENTRY("/Analyze/Appl_y as Filter", NULL, NULL, 0, "<Branch>", NULL),
300 ITEM_FACTORY_ENTRY("/Analyze/Apply as Filter/_Selected", NULL, match_selected_ptree_cb,
301 MATCH_SELECTED_REPLACE|MATCH_SELECTED_APPLY_NOW, NULL, NULL),
302 ITEM_FACTORY_ENTRY("/Analyze/Apply as Filter/_Not Selected", NULL, match_selected_ptree_cb,
303 MATCH_SELECTED_NOT|MATCH_SELECTED_APPLY_NOW, NULL, NULL),
304 ITEM_FACTORY_ENTRY("/Analyze/Apply as Filter/... _and Selected", NULL, match_selected_ptree_cb,
305 MATCH_SELECTED_AND|MATCH_SELECTED_APPLY_NOW, NULL, NULL),
306 ITEM_FACTORY_ENTRY("/Analyze/Apply as Filter/... _or Selected", NULL, match_selected_ptree_cb,
307 MATCH_SELECTED_OR|MATCH_SELECTED_APPLY_NOW, NULL, NULL),
308 ITEM_FACTORY_ENTRY("/Analyze/Apply as Filter/... a_nd not Selected", NULL, match_selected_ptree_cb,
309 MATCH_SELECTED_AND_NOT|MATCH_SELECTED_APPLY_NOW, NULL, NULL),
310 ITEM_FACTORY_ENTRY("/Analyze/Apply as Filter/... o_r not Selected", NULL, match_selected_ptree_cb,
311 MATCH_SELECTED_OR_NOT|MATCH_SELECTED_APPLY_NOW, NULL, NULL),
312 ITEM_FACTORY_ENTRY("/Analyze/_Prepare a Filter", NULL, NULL, 0, "<Branch>", NULL),
313 ITEM_FACTORY_ENTRY("/Analyze/Prepare a Filter/_Selected", NULL, match_selected_ptree_cb,
314 MATCH_SELECTED_REPLACE, NULL, NULL),
315 ITEM_FACTORY_ENTRY("/Analyze/Prepare a Filter/_Not Selected", NULL, match_selected_ptree_cb,
316 MATCH_SELECTED_NOT, NULL, NULL),
317 ITEM_FACTORY_ENTRY("/Analyze/Prepare a Filter/... _and Selected", NULL, match_selected_ptree_cb,
318 MATCH_SELECTED_AND, NULL, NULL),
319 ITEM_FACTORY_ENTRY("/Analyze/Prepare a Filter/... _or Selected", NULL, match_selected_ptree_cb,
320 MATCH_SELECTED_OR, NULL, NULL),
321 ITEM_FACTORY_ENTRY("/Analyze/Prepare a Filter/... a_nd not Selected", NULL, match_selected_ptree_cb,
322 MATCH_SELECTED_AND_NOT, NULL, NULL),
323 ITEM_FACTORY_ENTRY("/Analyze/Prepare a Filter/... o_r not Selected", NULL, match_selected_ptree_cb,
324 MATCH_SELECTED_OR_NOT, NULL, NULL),
325 ITEM_FACTORY_ENTRY("/Analyze/<separator>", NULL, NULL, 0, "<Separator>", NULL),
326 ITEM_FACTORY_ENTRY("/Analyze/_Enabled Protocols...", "<shift><control>R", proto_cb, 0, NULL, NULL),
327 ITEM_FACTORY_ENTRY("/Analyze/Decode _As...", NULL, decode_as_cb,
329 ITEM_FACTORY_ENTRY("/Analyze/_User Specified Decodes...", NULL,
330 decode_show_cb, 0, NULL, NULL),
331 ITEM_FACTORY_ENTRY("/Analyze/<separator>", NULL, NULL, 0, "<Separator>", NULL),
332 ITEM_FACTORY_ENTRY("/Analyze/_Follow TCP Stream", NULL,
333 follow_stream_cb, 0, NULL, NULL),
334 ITEM_FACTORY_ENTRY("/_Statistics", NULL, NULL, 0, "<Branch>", NULL),
335 ITEM_FACTORY_ENTRY("/Statistics/_Summary", NULL, summary_open_cb, 0, NULL, NULL),
336 ITEM_FACTORY_ENTRY("/Statistics/_Protocol Hierarchy", NULL,
337 proto_hier_stats_cb, 0, NULL, NULL),
338 ITEM_FACTORY_ENTRY("/Statistics/Conversations", NULL,
339 init_conversation_notebook_cb, 0, NULL, NULL),
340 ITEM_FACTORY_ENTRY("/Statistics/Endpoints", NULL,
341 init_hostlist_notebook_cb, 0, NULL, NULL),
342 ITEM_FACTORY_ENTRY("/_Help", NULL, NULL, 0, "<Branch>", NULL),
343 ITEM_FACTORY_STOCK_ENTRY("/Help/_Contents", "F1", help_cb, 0, GTK_STOCK_HELP),
344 ITEM_FACTORY_ENTRY("/Help/_Supported Protocols", NULL, supported_cb, 0, NULL, NULL),
345 #if (GLIB_MAJOR_VERSION >= 2)
346 /* currently, glib1.x can't start a webbrowser, see webbrowser.c for details */
347 ITEM_FACTORY_ENTRY("/Help/Manual Pages", NULL, NULL, 0, "<Branch>", NULL),
348 ITEM_FACTORY_ENTRY("/Help/Manual Pages/Ethereal", NULL, url_localpage_cb, LOCALPAGE_MAN_ETHEREAL, NULL, NULL),
349 ITEM_FACTORY_ENTRY("/Help/Manual Pages/Ethereal Filter", NULL, url_localpage_cb, LOCALPAGE_MAN_ETHEREAL_FILTER, NULL, NULL),
350 ITEM_FACTORY_ENTRY("/Help/Manual Pages/<separator>", NULL, NULL, 0, "<Separator>", NULL),
351 ITEM_FACTORY_ENTRY("/Help/Manual Pages/Tethereal", NULL, url_localpage_cb, LOCALPAGE_MAN_TETHEREAL, NULL, NULL),
352 ITEM_FACTORY_ENTRY("/Help/Manual Pages/Mergecap", NULL, url_localpage_cb, LOCALPAGE_MAN_MERGECAP, NULL, NULL),
353 ITEM_FACTORY_ENTRY("/Help/Manual Pages/Editcap", NULL, url_localpage_cb, LOCALPAGE_MAN_EDITCAP, NULL, NULL),
354 ITEM_FACTORY_ENTRY("/Help/Manual Pages/Text2pcap", NULL, url_localpage_cb, LOCALPAGE_MAN_TEXT2PCAP, NULL, NULL),
355 ITEM_FACTORY_ENTRY("/Help/Ethereal Online", NULL, NULL, 0, "<Branch>", NULL),
356 ITEM_FACTORY_STOCK_ENTRY("/Help/Ethereal Online/Home Page", NULL, url_onlinepage_cb, ONLINEPAGE_HOME, GTK_STOCK_HOME),
357 ITEM_FACTORY_ENTRY("/Help/Ethereal Online/User's Guide", NULL, url_onlinepage_cb, ONLINEPAGE_USERGUIDE, NULL, NULL),
358 ITEM_FACTORY_ENTRY("/Help/Ethereal Online/FAQ's", NULL, url_onlinepage_cb, ONLINEPAGE_FAQ, NULL, NULL),
359 ITEM_FACTORY_ENTRY("/Help/Ethereal Online/Downloads", NULL, url_onlinepage_cb, ONLINEPAGE_DOWNLOAD, NULL, NULL),
360 ITEM_FACTORY_ENTRY("/Help/Ethereal Online/Example Files", NULL, url_onlinepage_cb, ONLINEPAGE_SAMPLE, NULL, NULL),
362 ITEM_FACTORY_ENTRY("/Help/<separator>", NULL, NULL, 0, "<Separator>", NULL),
363 ITEM_FACTORY_ENTRY("/Help/_About Ethereal", NULL, about_ethereal_cb,
368 /* calculate the number of menu_items */
369 static int nmenu_items = sizeof(menu_items) / sizeof(menu_items[0]);
371 /* packet list popup */
372 static GtkItemFactoryEntry packet_list_menu_items[] =
374 ITEM_FACTORY_ENTRY("/Follow TCP Stream", NULL, follow_stream_cb,
376 ITEM_FACTORY_ENTRY("/Decode As...", NULL, decode_as_cb, 0, NULL, NULL),
377 ITEM_FACTORY_ENTRY("/Display Filters...", NULL, dfilter_dialog_cb,
379 ITEM_FACTORY_ENTRY("/<separator>", NULL, NULL, 0, "<Separator>", NULL),
380 ITEM_FACTORY_ENTRY("/Mark Packet", NULL, mark_frame_cb, 0, NULL, NULL),
381 ITEM_FACTORY_ENTRY("/Time Reference", NULL, NULL, 0, "<Branch>", NULL),
382 ITEM_FACTORY_ENTRY("/Time Reference/Set Time Reference (toggle)", NULL, reftime_frame_cb, REFTIME_TOGGLE, NULL, NULL),
383 ITEM_FACTORY_ENTRY("/Time Reference/Find Next", NULL, reftime_frame_cb, REFTIME_FIND_NEXT, NULL, NULL),
384 ITEM_FACTORY_ENTRY("/Time Reference/Find Previous", NULL, reftime_frame_cb, REFTIME_FIND_PREV, NULL, NULL),
385 ITEM_FACTORY_ENTRY("/Apply as Filter", NULL, NULL, 0, "<Branch>", NULL),
386 ITEM_FACTORY_ENTRY("/Apply as Filter/_Selected", NULL, match_selected_plist_cb,
387 MATCH_SELECTED_REPLACE|MATCH_SELECTED_APPLY_NOW, NULL, NULL),
388 ITEM_FACTORY_ENTRY("/Apply as Filter/_Not Selected", NULL, match_selected_plist_cb,
389 MATCH_SELECTED_NOT|MATCH_SELECTED_APPLY_NOW, NULL, NULL),
390 ITEM_FACTORY_ENTRY("/Apply as Filter/... _and Selected", NULL, match_selected_plist_cb,
391 MATCH_SELECTED_AND|MATCH_SELECTED_APPLY_NOW, NULL, NULL),
392 ITEM_FACTORY_ENTRY("/Apply as Filter/... _or Selected", NULL, match_selected_plist_cb,
393 MATCH_SELECTED_OR|MATCH_SELECTED_APPLY_NOW, NULL, NULL),
394 ITEM_FACTORY_ENTRY("/Apply as Filter/... a_nd not Selected", NULL, match_selected_plist_cb,
395 MATCH_SELECTED_AND_NOT|MATCH_SELECTED_APPLY_NOW, NULL, NULL),
396 ITEM_FACTORY_ENTRY("/Apply as Filter/... o_r not Selected", NULL, match_selected_plist_cb,
397 MATCH_SELECTED_OR_NOT|MATCH_SELECTED_APPLY_NOW, NULL, NULL),
399 ITEM_FACTORY_ENTRY("/Prepare a Filter", NULL, NULL, 0, "<Branch>", NULL),
400 ITEM_FACTORY_ENTRY("/Prepare a Filter/_Selected", NULL, match_selected_plist_cb,
401 MATCH_SELECTED_REPLACE, NULL, NULL),
402 ITEM_FACTORY_ENTRY("/Prepare a Filter/_Not Selected", NULL, match_selected_plist_cb,
403 MATCH_SELECTED_NOT, NULL, NULL),
404 ITEM_FACTORY_ENTRY("/Prepare a Filter/... _and Selected", NULL, match_selected_plist_cb,
405 MATCH_SELECTED_AND, NULL, NULL),
406 ITEM_FACTORY_ENTRY("/Prepare a Filter/... _or Selected", NULL, match_selected_plist_cb,
407 MATCH_SELECTED_OR, NULL, NULL),
408 ITEM_FACTORY_ENTRY("/Prepare a Filter/... a_nd not Selected", NULL, match_selected_plist_cb,
409 MATCH_SELECTED_AND_NOT, NULL, NULL),
410 ITEM_FACTORY_ENTRY("/Prepare a Filter/... o_r not Selected", NULL, match_selected_plist_cb,
411 MATCH_SELECTED_OR_NOT, NULL, NULL),
413 ITEM_FACTORY_ENTRY("/<separator>", NULL, NULL, 0, "<Separator>", NULL),
414 ITEM_FACTORY_ENTRY("/Coloring Rules...", NULL, color_display_cb,
416 ITEM_FACTORY_ENTRY("/Print...", NULL, file_print_cmd_cb, 0, NULL, NULL),
417 ITEM_FACTORY_ENTRY("/Show Packet in New Window", NULL, new_window_cb,
421 static GtkItemFactoryEntry tree_view_menu_items[] =
423 ITEM_FACTORY_ENTRY("/Follow TCP Stream", NULL, follow_stream_cb,
425 ITEM_FACTORY_ENTRY("/Decode As...", NULL, decode_as_cb, 0, NULL, NULL),
426 ITEM_FACTORY_ENTRY("/Display Filters...", NULL, dfilter_dialog_cb,
428 ITEM_FACTORY_ENTRY("/<separator>", NULL, NULL, 0, "<Separator>", NULL),
429 ITEM_FACTORY_ENTRY("/_Resolve Name", NULL, resolve_name_cb, 0, NULL, NULL),
430 ITEM_FACTORY_ENTRY("/_Go to Corresponding Packet", NULL, goto_framenum_cb, 0, NULL, NULL),
431 ITEM_FACTORY_ENTRY("/_Export Selected Packet Bytes...", NULL, savehex_cb,
433 ITEM_FACTORY_ENTRY("/Protocol Preferences...", NULL, properties_cb,
435 ITEM_FACTORY_ENTRY("/Apply as Filter", NULL, NULL, 0, "<Branch>", NULL),
436 ITEM_FACTORY_ENTRY("/Apply as Filter/_Selected", NULL, match_selected_ptree_cb,
437 MATCH_SELECTED_REPLACE|MATCH_SELECTED_APPLY_NOW, NULL, NULL),
438 ITEM_FACTORY_ENTRY("/Apply as Filter/_Not Selected", NULL, match_selected_ptree_cb,
439 MATCH_SELECTED_NOT|MATCH_SELECTED_APPLY_NOW, NULL, NULL),
440 ITEM_FACTORY_ENTRY("/Apply as Filter/... _and Selected", NULL, match_selected_ptree_cb,
441 MATCH_SELECTED_AND|MATCH_SELECTED_APPLY_NOW, NULL, NULL),
442 ITEM_FACTORY_ENTRY("/Apply as Filter/... _or Selected", NULL, match_selected_ptree_cb,
443 MATCH_SELECTED_OR|MATCH_SELECTED_APPLY_NOW, NULL, NULL),
444 ITEM_FACTORY_ENTRY("/Apply as Filter/... a_nd not Selected", NULL, match_selected_ptree_cb,
445 MATCH_SELECTED_AND_NOT|MATCH_SELECTED_APPLY_NOW, NULL, NULL),
446 ITEM_FACTORY_ENTRY("/Apply as Filter/... o_r not Selected", NULL, match_selected_ptree_cb,
447 MATCH_SELECTED_OR_NOT|MATCH_SELECTED_APPLY_NOW, NULL, NULL),
449 ITEM_FACTORY_ENTRY("/Prepare a Filter", NULL, NULL, 0, "<Branch>", NULL),
450 ITEM_FACTORY_ENTRY("/Prepare a Filter/_Selected", NULL, match_selected_ptree_cb,
451 MATCH_SELECTED_REPLACE, NULL, NULL),
452 ITEM_FACTORY_ENTRY("/Prepare a Filter/_Not Selected", NULL, match_selected_ptree_cb,
453 MATCH_SELECTED_NOT, NULL, NULL),
454 ITEM_FACTORY_ENTRY("/Prepare a Filter/... _and Selected", NULL, match_selected_ptree_cb,
455 MATCH_SELECTED_AND, NULL, NULL),
456 ITEM_FACTORY_ENTRY("/Prepare a Filter/... _or Selected", NULL, match_selected_ptree_cb,
457 MATCH_SELECTED_OR, NULL, NULL),
458 ITEM_FACTORY_ENTRY("/Prepare a Filter/... a_nd not Selected", NULL, match_selected_ptree_cb,
459 MATCH_SELECTED_AND_NOT, NULL, NULL),
460 ITEM_FACTORY_ENTRY("/Prepare a Filter/... o_r not Selected", NULL, match_selected_ptree_cb,
461 MATCH_SELECTED_OR_NOT, NULL, NULL),
462 ITEM_FACTORY_ENTRY("/<separator>", NULL, NULL, 0, "<Separator>", NULL),
463 ITEM_FACTORY_ENTRY("/Collapse All", NULL, collapse_all_cb, 0, NULL, NULL),
464 ITEM_FACTORY_ENTRY("/Expand All", NULL, expand_all_cb, 0, NULL, NULL),
465 ITEM_FACTORY_ENTRY("/Expand Tree", NULL, expand_tree_cb, 0, NULL, NULL)
468 static GtkItemFactoryEntry hexdump_menu_items[] =
470 ITEM_FACTORY_ENTRY("/Follow TCP Stream", NULL, follow_stream_cb,
472 ITEM_FACTORY_ENTRY("/Decode As...", NULL, decode_as_cb, 0, NULL, NULL),
473 ITEM_FACTORY_ENTRY("/Display Filters...", NULL, dfilter_dialog_cb,
475 ITEM_FACTORY_ENTRY("/Export Selected Packet Bytes...", NULL, savehex_cb,
477 ITEM_FACTORY_ENTRY("/Copy Packet Bytes into Clipboard", NULL, copy_hex_cb,
481 static int initialize = TRUE;
482 static GtkItemFactory *main_menu_factory = NULL;
483 static GtkItemFactory *packet_list_menu_factory = NULL;
484 static GtkItemFactory *tree_view_menu_factory = NULL;
485 static GtkItemFactory *hexdump_menu_factory = NULL;
487 static GSList *popup_menu_list = NULL;
489 static GtkAccelGroup *grp;
492 main_menu_new(GtkAccelGroup ** table) {
495 grp = gtk_accel_group_new();
500 menubar = main_menu_factory->widget;
514 packet_list_menu_factory = gtk_item_factory_new(GTK_TYPE_MENU, "<main>", NULL);
515 popup_menu_object = gtk_menu_new();
516 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);
517 OBJECT_SET_DATA(popup_menu_object, PM_PACKET_LIST_KEY,
518 packet_list_menu_factory->widget);
519 popup_menu_list = g_slist_append((GSList *)popup_menu_list, packet_list_menu_factory);
521 tree_view_menu_factory = gtk_item_factory_new(GTK_TYPE_MENU, "<main>", NULL);
522 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);
523 OBJECT_SET_DATA(popup_menu_object, PM_TREE_VIEW_KEY,
524 tree_view_menu_factory->widget);
525 popup_menu_list = g_slist_append((GSList *)popup_menu_list, tree_view_menu_factory);
527 hexdump_menu_factory = gtk_item_factory_new(GTK_TYPE_MENU, "<main>", NULL);
528 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);
529 OBJECT_SET_DATA(popup_menu_object, PM_HEXDUMP_KEY,
530 hexdump_menu_factory->widget);
531 popup_menu_list = g_slist_append((GSList *)popup_menu_list, hexdump_menu_factory);
534 main_menu_factory = gtk_item_factory_new(GTK_TYPE_MENU_BAR, "<main>", grp);
535 gtk_item_factory_create_items_ac(main_menu_factory, nmenu_items, menu_items, NULL, 2);
537 merge_all_tap_menus(tap_menu_tree_root);
539 /* Initialize enabled/disabled state of menu items */
540 set_menus_for_unsaved_capture_file(FALSE);
541 set_menus_for_capture_file(FALSE);
543 /* Un-#if this when we actually implement Cut/Copy/Paste.
544 Then make sure you enable them when they can be done. */
545 set_menu_sensitivity(main_menu_factory, "/Edit/Cut", FALSE);
546 set_menu_sensitivity(main_menu_factory, "/Edit/Copy", FALSE);
547 set_menu_sensitivity(main_menu_factory, "/Edit/Paste", FALSE);
550 set_menus_for_captured_packets(FALSE);
551 set_menus_for_selected_packet(&cfile);
552 set_menus_for_selected_tree_row(&cfile);
554 /* init with an empty recent files list */
555 clear_menu_recent_capture_file_cmd_cb(NULL, NULL);
560 gint tap_menu_item_add_compare(gconstpointer a, gconstpointer b)
563 ((const menu_item_t *) a)->name,
564 ((const menu_item_t *) b)->name);
568 /* add a menuitem below the current node */
569 GList * tap_menu_item_add(
572 GtkItemFactoryCallback callback,
573 gboolean (*selected_packet_enabled)(frame_data *, epan_dissect_t *),
574 gboolean (*selected_tree_row_enabled)(field_info *),
575 gpointer callback_data,
582 child = g_malloc(sizeof (menu_item_t));
583 child->group = group;
585 child->callback = callback;
586 child->selected_packet_enabled = selected_packet_enabled;
587 child->selected_tree_row_enabled = selected_tree_row_enabled;
588 child->callback_data = callback_data;
589 child->enabled = FALSE;
590 child->children = NULL;
592 /* insert the new child node into the parent */
593 curr = curnode->data;
594 curr->children = g_list_insert_sorted(curr->children, child, tap_menu_item_add_compare);
596 /* return the new node */
597 /* XXX: improve this */
598 return g_list_find(curr->children, child);
602 * Add a new menu item for a tap.
603 * This must be called after we've created the main menu, so it can't
604 * be called from the routine that registers taps - we have to introduce
605 * another per-tap registration routine.
607 * "callback" gets called when the menu item is selected; it should do
608 * the work of creating the tap window.
610 * "selected_packet_enabled" gets called by "set_menus_for_selected_packet()";
611 * it's passed a Boolean that's TRUE if a packet is selected and FALSE
612 * otherwise, and should return TRUE if the tap will work now (which
613 * might depend on whether a packet is selected and, if one is, on the
614 * packet) and FALSE if not.
616 * "selected_tree_row_enabled" gets called by
617 * "set_menus_for_selected_tree_row()"; it's passed a Boolean that's TRUE if
618 * a protocol tree row is selected and FALSE otherwise, and should return
619 * TRUE if the tap will work now (which might depend on whether a tree row
620 * is selected and, if one is, on the tree row) and FALSE if not.
623 register_tap_menu_item(
625 REGISTER_TAP_GROUP_E group,
626 GtkItemFactoryCallback callback,
627 gboolean (*selected_packet_enabled)(frame_data *, epan_dissect_t *),
628 gboolean (*selected_tree_row_enabled)(field_info *),
629 gpointer callback_data)
631 /*static const char toolspath[] = "/Statistics/";*/
641 * The menu path must be relative.
643 g_assert(*name != '/');
646 case(REGISTER_TAP_GROUP_GENERIC): toolspath = "/Statistics/"; break;
647 case(REGISTER_TAP_GROUP_CONVERSATION_LIST): toolspath = "/Statistics/_Conversation List/"; break;
648 case(REGISTER_TAP_GROUP_ENDPOINT_LIST): toolspath = "/Statistics/_Endpoint List/"; break;
649 case(REGISTER_TAP_GROUP_RESPONSE_TIME): toolspath = "/Statistics/Service _Response Time/"; break;
650 case(REGISTER_TAP_GROUP_NONE): toolspath = "/Statistics/"; break;
656 /* add the (empty) root node, if not already done */
657 if(tap_menu_tree_root == NULL) {
658 child = g_malloc0(sizeof (menu_item_t));
659 tap_menu_tree_root = g_list_append(NULL, child);
663 * Create any submenus required.
665 curnode = tap_menu_tree_root;
667 while ((p = strchr(p, '/')) != NULL) {
669 * OK, everything between "name" and "p" is
670 * a menu relative subtree into which the menu item
673 * Construct the absolute path name of that subtree.
675 menupathlen = strlen(toolspath) + 1 + (p - name);
676 menupath = g_malloc(menupathlen);
677 strcpy(menupath, toolspath);
678 strncat(menupath, name, p - name);
681 * Does there exist an entry with that path at this
682 * level of the Analyze menu tree?
684 child = curnode->data;
685 for (childnode = child->children; childnode != NULL; childnode = childnode->next) {
686 child = childnode->data;
687 if (strcmp(child->name, menupath) == 0)
690 if (childnode == NULL) {
692 * No. Create such an item as a subtree, and
693 * add it to the Tools menu tree.
695 childnode = tap_menu_item_add(
696 menupath, group, NULL, NULL ,NULL, NULL, curnode);
699 * Yes. We don't need this "menupath" any longer.
706 * Skip over the '/' we found.
712 * Construct the main menu path for the menu item.
714 menupathlen = strlen(toolspath) + 1 + strlen(name);
715 menupath = g_malloc(menupathlen);
716 strcpy(menupath, toolspath);
717 strcat(menupath, name);
720 * Construct an item factory entry for the item, and add it to
724 menupath, group, callback,
725 selected_packet_enabled, selected_tree_row_enabled,
726 callback_data, curnode);
730 guint merge_tap_menus_layered(GList *node, gint group) {
731 GtkItemFactoryEntry *entry;
734 menu_item_t *node_data = node->data;
737 * Is this a leaf node or an interior node?
739 if (node_data->children == NULL) {
745 * The root node doesn't correspond to a menu tree item; it
746 * has a null name pointer.
748 if (node_data->name != NULL && group == node_data->group) {
749 entry = g_malloc0(sizeof (GtkItemFactoryEntry));
750 entry->path = node_data->name;
751 entry->callback = node_data->callback;
752 gtk_item_factory_create_item(main_menu_factory, entry, node_data->callback_data, 2);
753 set_menu_sensitivity(main_menu_factory, node_data->name, FALSE); /* no capture file yet */
758 * It's an interior node; call
759 * "merge_tap_menus_layered()" on all its children
763 * The root node doesn't correspond to a menu tree item; it
764 * has a null name pointer.
766 if (node_data->name != NULL && group == node_data->group) {
767 entry = g_malloc0(sizeof (GtkItemFactoryEntry));
768 entry->path = node_data->name;
769 entry->item_type = "<Branch>";
770 gtk_item_factory_create_item(main_menu_factory, entry,
772 set_menu_sensitivity(main_menu_factory, node_data->name,
773 FALSE); /* no children yet */
777 for (child = node_data->children; child != NULL; child =
779 added += merge_tap_menus_layered(child, group);
787 void merge_all_tap_menus(GList *node) {
788 GtkItemFactoryEntry *entry;
790 entry = g_malloc0(sizeof (GtkItemFactoryEntry));
791 entry->item_type = "<Separator>";
792 entry->path = "/Statistics/";
795 * merge only the menu items of the specific group,
796 * and then append a seperator
798 if (merge_tap_menus_layered(node, REGISTER_TAP_GROUP_GENERIC)) {
799 gtk_item_factory_create_item(main_menu_factory, entry, NULL, 2);
801 if (merge_tap_menus_layered(node, REGISTER_TAP_GROUP_CONVERSATION_LIST)) {
802 /*gtk_item_factory_create_item(main_menu_factory, entry, NULL, 2);*/
804 if (merge_tap_menus_layered(node, REGISTER_TAP_GROUP_ENDPOINT_LIST)) {
805 /*gtk_item_factory_create_item(main_menu_factory, entry, NULL, 2);*/
807 if (merge_tap_menus_layered(node, REGISTER_TAP_GROUP_RESPONSE_TIME)) {
808 gtk_item_factory_create_item(main_menu_factory, entry, NULL, 2);
810 if (merge_tap_menus_layered(node, REGISTER_TAP_GROUP_NONE)) {
811 /*gtk_item_factory_create_item(main_menu_factory, entry, NULL, 2);*/
818 * Enable/disable menu sensitivity.
821 set_menu_sensitivity(GtkItemFactory *ifactory, const gchar *path, gint val)
824 GtkWidget *menu_item;
829 /* the underscore character regularly confuses things, as it will prevent finding
830 * the menu_item, so it has to be removed first */
831 dup = g_strdup(path);
842 if (ifactory == NULL) {
844 * Do it for all pop-up menus.
846 for (menu_list = popup_menu_list; menu_list != NULL;
847 menu_list = g_slist_next(menu_list))
848 set_menu_sensitivity(menu_list->data, dup, val);
851 * Do it for that particular menu.
853 if ((menu_item = gtk_item_factory_get_widget(ifactory, dup)) != NULL) {
854 if (GTK_IS_MENU(menu_item)) {
856 * "dup" refers to a submenu; "gtk_item_factory_get_widget()"
857 * gets the menu, not the item that, when selected, pops up
860 * We have to change the latter item's sensitivity, so that
861 * it shows up normally if sensitive and grayed-out if
864 menu_item = gtk_menu_get_attach_widget(GTK_MENU(menu_item));
866 gtk_widget_set_sensitive(menu_item, val);
868 /* be sure this menu item *is* existing */
869 g_assert_not_reached();
877 set_menu_object_data_meat(GtkItemFactory *ifactory, gchar *path, gchar *key, gpointer data)
879 GtkWidget *menu = NULL;
881 if ((menu = gtk_item_factory_get_widget(ifactory, path)) != NULL)
882 OBJECT_SET_DATA(menu, key, data);
886 set_menu_object_data (gchar *path, gchar *key, gpointer data) {
887 GSList *menu_list = popup_menu_list;
888 gchar *shortpath = strrchr(path, '/');
890 set_menu_object_data_meat(main_menu_factory, path, key, data);
891 while (menu_list != NULL) {
892 set_menu_object_data_meat(menu_list->data, shortpath, key, data);
893 menu_list = g_slist_next(menu_list);
898 /* Recently used capture files submenu:
899 * Submenu containing the recently used capture files.
900 * The capture filenames are always kept with the absolute path, to be independant
901 * of the current path.
902 * They are only stored inside the labels of the submenu (no separate list). */
904 #define MENU_RECENT_FILES_PATH "/File/Open Recent"
905 #define MENU_RECENT_FILES_KEY "Recent File Name"
908 update_menu_recent_capture_file1(GtkWidget *widget, gpointer cnt) {
909 gchar *widget_cf_name;
911 widget_cf_name = OBJECT_GET_DATA(widget, MENU_RECENT_FILES_KEY);
913 /* if this menu item is a file, count it */
914 if (widget_cf_name) {
920 /* update the menu */
922 update_menu_recent_capture_file(GtkWidget *submenu_recent_files) {
925 gtk_container_foreach(GTK_CONTAINER(submenu_recent_files),
926 update_menu_recent_capture_file1, &cnt);
928 /* make parent menu item sensitive only, if we have any valid files in the list */
929 set_menu_sensitivity(main_menu_factory, MENU_RECENT_FILES_PATH, cnt);
933 /* remove the capture filename from the "Recent Files" menu */
935 remove_menu_recent_capture_file(GtkWidget *widget, gpointer unused _U_) {
936 GtkWidget *submenu_recent_files;
937 gchar *widget_cf_name;
940 widget_cf_name = OBJECT_GET_DATA(widget, MENU_RECENT_FILES_KEY);
941 g_free(widget_cf_name);
943 /* get the submenu container item */
944 submenu_recent_files = gtk_item_factory_get_widget(main_menu_factory, MENU_RECENT_FILES_PATH);
946 /* XXX: is this all we need to do, to free the menu item and its label?
947 The reference count of widget will go to 0, so it'll be freed;
948 will that free the label? */
949 gtk_container_remove(GTK_CONTAINER(submenu_recent_files), widget);
953 /* callback, if the user pushed the <Clear File List> item */
955 clear_menu_recent_capture_file_cmd_cb(GtkWidget *w _U_, gpointer unused _U_) {
956 GtkWidget *submenu_recent_files;
959 submenu_recent_files = gtk_item_factory_get_widget(main_menu_factory, MENU_RECENT_FILES_PATH);
961 gtk_container_foreach(GTK_CONTAINER(submenu_recent_files),
962 remove_menu_recent_capture_file, NULL);
964 update_menu_recent_capture_file(submenu_recent_files);
968 /* callback, if the user pushed a recent file submenu item */
970 menu_open_recent_file_cmd(GtkWidget *w)
972 GtkWidget *submenu_recent_files;
973 GtkWidget *menu_item_child;
977 submenu_recent_files = gtk_item_factory_get_widget(main_menu_factory, MENU_RECENT_FILES_PATH);
979 /* get capture filename from the menu item label */
980 menu_item_child = (GTK_BIN(w))->child;
981 gtk_label_get(GTK_LABEL(menu_item_child), &cf_name);
983 /* open and read the capture file (this will close an existing file) */
984 if ((err = cf_open(cf_name, FALSE, &cfile)) == 0) {
987 /* the capture file isn't existing any longer, remove menu item */
988 /* XXX: ask user to remove item, it's maybe only a temporary problem */
989 remove_menu_recent_capture_file(w, NULL);
992 update_menu_recent_capture_file(submenu_recent_files);
995 static void menu_open_recent_file_answered_cb(gpointer dialog _U_, gint btn, gpointer data _U_)
999 /* save file first */
1000 file_save_as_cmd(after_save_open_recent_file, data);
1004 menu_open_recent_file_cmd(data);
1006 case(ESD_BTN_CANCEL):
1009 g_assert_not_reached();
1014 menu_open_recent_file_cmd_cb(GtkWidget *widget, gpointer data _U_) {
1018 if((cfile.state != FILE_CLOSED) && !cfile.user_saved && prefs.gui_ask_unsaved) {
1019 /* user didn't saved his current file, ask him */
1020 dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_YES_NO_CANCEL,
1021 PRIMARY_TEXT_START "Save capture file before opening a new one?" PRIMARY_TEXT_END "\n\n"
1022 "If you open a new capture file without saving, your current capture data will be discarded.");
1023 simple_dialog_set_cb(dialog, menu_open_recent_file_answered_cb, widget);
1025 /* unchanged file */
1026 menu_open_recent_file_cmd(widget);
1030 /* add the capture filename (with an absolute path) to the "Recent Files" menu */
1032 add_menu_recent_capture_file_absolute(gchar *cf_name) {
1033 GtkWidget *submenu_recent_files;
1034 GList *menu_item_list;
1036 gchar *widget_cf_name;
1037 gchar *normalized_cf_name;
1038 GtkWidget *menu_item;
1043 normalized_cf_name = g_strdup(cf_name);
1045 /* replace all slashes by backslashes */
1046 g_strdelimit(normalized_cf_name, "/", '\\');
1049 /* get the submenu container item */
1050 submenu_recent_files = gtk_item_factory_get_widget(main_menu_factory, MENU_RECENT_FILES_PATH);
1052 /* convert container to a GList */
1053 menu_item_list = gtk_container_children(GTK_CONTAINER(submenu_recent_files));
1055 /* iterate through list items of menu_item_list,
1056 * removing special items, a maybe duplicate entry and every item above count_max */
1058 for (li = g_list_first(menu_item_list); li; li = li->next, cnt++) {
1059 /* get capture filename */
1060 menu_item = GTK_WIDGET(li->data);
1061 widget_cf_name = OBJECT_GET_DATA(menu_item, MENU_RECENT_FILES_KEY);
1063 /* if this element string is one of our special items (seperator, ...) or
1064 * already in the list or
1065 * this element is above maximum count (too old), remove it */
1066 if (!widget_cf_name ||
1068 /* do a case insensitive compare on win32 */
1069 #if GLIB_MAJOR_VERSION < 2
1070 g_strncasecmp(widget_cf_name, normalized_cf_name, 1000) == 0 ||
1072 g_ascii_strncasecmp(widget_cf_name, normalized_cf_name, 1000) == 0 ||
1075 /* do a case sensitive compare on unix */
1076 strncmp(widget_cf_name, normalized_cf_name, 1000) == 0 ||
1078 cnt >= prefs.gui_recent_files_count_max) {
1079 remove_menu_recent_capture_file(li->data, NULL);
1084 g_list_free(menu_item_list);
1086 /* add new item at latest position */
1087 menu_item = gtk_menu_item_new_with_label(normalized_cf_name);
1088 OBJECT_SET_DATA(menu_item, MENU_RECENT_FILES_KEY, normalized_cf_name);
1089 gtk_menu_prepend (GTK_MENU(submenu_recent_files), menu_item);
1090 SIGNAL_CONNECT_OBJECT(GTK_OBJECT(menu_item), "activate",
1091 menu_open_recent_file_cmd_cb, (GtkObject *) menu_item);
1092 gtk_widget_show (menu_item);
1094 /* add seperator at last position */
1095 menu_item = gtk_menu_item_new();
1096 gtk_menu_append (GTK_MENU(submenu_recent_files), menu_item);
1097 gtk_widget_show (menu_item);
1099 /* add new "clear list" item at last position */
1100 #if GTK_MAJOR_VERSION < 2
1101 menu_item = gtk_menu_item_new_with_label("<Clear File List>");
1103 menu_item = gtk_image_menu_item_new_from_stock(GTK_STOCK_CLEAR, NULL);
1105 gtk_menu_append (GTK_MENU(submenu_recent_files), menu_item);
1106 SIGNAL_CONNECT_OBJECT(GTK_OBJECT(menu_item), "activate",
1107 clear_menu_recent_capture_file_cmd_cb, (GtkObject *) menu_item);
1108 gtk_widget_show (menu_item);
1110 update_menu_recent_capture_file(submenu_recent_files);
1114 /* add the capture filename to the "Recent Files" menu */
1115 /* (will change nothing, if this filename is already in the menu) */
1117 add_menu_recent_capture_file(gchar *cf_name) {
1122 /* if this filename is an absolute path, we can use it directly */
1123 if (g_path_is_absolute(cf_name)) {
1124 add_menu_recent_capture_file_absolute(cf_name);
1128 /* this filename is not an absolute path, prepend the current dir */
1129 curr = g_get_current_dir();
1130 absolute = g_strdup_printf("%s%s%s", curr, G_DIR_SEPARATOR_S, cf_name);
1131 add_menu_recent_capture_file_absolute(absolute);
1137 /* write all capture filenames of the menu to the user's recent file */
1139 menu_recent_file_write_all(FILE *rf) {
1140 GtkWidget *submenu_recent_files;
1146 submenu_recent_files = gtk_item_factory_get_widget(main_menu_factory, MENU_RECENT_FILES_PATH);
1148 /* we have to iterate backwards through the children's list,
1149 * so we get the latest item last in the file.
1150 * (don't use gtk_container_foreach() here, it will return the wrong iteration order) */
1151 children = gtk_container_children(GTK_CONTAINER(submenu_recent_files));
1152 child = g_list_last(children);
1153 while(child != NULL) {
1154 /* get capture filename from the menu item label */
1155 cf_name = OBJECT_GET_DATA(child->data, MENU_RECENT_FILES_KEY);
1157 fprintf (rf, RECENT_KEY_CAPTURE_FILE ": %s\n", cf_name);
1160 child = g_list_previous(child);
1163 g_list_free(children);
1168 main_toolbar_show_cb(GtkWidget *w _U_, gpointer d _U_)
1171 /* save current setting in recent */
1172 recent.main_toolbar_show = GTK_CHECK_MENU_ITEM(w)->active;
1174 main_widgets_show_or_hide();
1179 filter_toolbar_show_cb(GtkWidget *w _U_, gpointer d _U_)
1182 /* save current setting in recent */
1183 recent.filter_toolbar_show = GTK_CHECK_MENU_ITEM(w)->active;
1185 main_widgets_show_or_hide();
1190 packet_list_show_cb(GtkWidget *w _U_, gpointer d _U_)
1193 /* save current setting in recent */
1194 recent.packet_list_show = GTK_CHECK_MENU_ITEM(w)->active;
1196 main_widgets_show_or_hide();
1201 tree_view_show_cb(GtkWidget *w _U_, gpointer d _U_)
1204 /* save current setting in recent */
1205 recent.tree_view_show = GTK_CHECK_MENU_ITEM(w)->active;
1207 main_widgets_show_or_hide();
1212 byte_view_show_cb(GtkWidget *w _U_, gpointer d _U_)
1215 /* save current setting in recent */
1216 recent.byte_view_show = GTK_CHECK_MENU_ITEM(w)->active;
1218 main_widgets_show_or_hide();
1223 statusbar_show_cb(GtkWidget *w _U_, gpointer d _U_)
1226 /* save current setting in recent */
1227 recent.statusbar_show = GTK_CHECK_MENU_ITEM(w)->active;
1229 main_widgets_show_or_hide();
1234 timestamp_absolute_cb(GtkWidget *w _U_, gpointer d _U_)
1236 if (recent.gui_time_format != TS_ABSOLUTE) {
1237 set_timestamp_setting(TS_ABSOLUTE);
1238 recent.gui_time_format = TS_ABSOLUTE;
1239 change_time_formats(&cfile);
1244 timestamp_absolute_date_cb(GtkWidget *w _U_, gpointer d _U_)
1246 if (recent.gui_time_format != TS_ABSOLUTE_WITH_DATE) {
1247 set_timestamp_setting(TS_ABSOLUTE_WITH_DATE);
1248 recent.gui_time_format = TS_ABSOLUTE_WITH_DATE;
1249 change_time_formats(&cfile);
1254 timestamp_relative_cb(GtkWidget *w _U_, gpointer d _U_)
1256 if (recent.gui_time_format != TS_RELATIVE) {
1257 set_timestamp_setting(TS_RELATIVE);
1258 recent.gui_time_format = TS_RELATIVE;
1259 change_time_formats(&cfile);
1264 timestamp_delta_cb(GtkWidget *w _U_, gpointer d _U_)
1266 if (recent.gui_time_format != TS_DELTA) {
1267 set_timestamp_setting(TS_DELTA);
1268 recent.gui_time_format = TS_DELTA;
1269 change_time_formats(&cfile);
1274 menu_name_resolution_changed(void)
1276 GtkWidget *menu = NULL;
1278 menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Name Resolution/Enable for MAC Layer");
1279 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), g_resolv_flags & RESOLV_MAC);
1281 menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Name Resolution/Enable for Network Layer");
1282 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), g_resolv_flags & RESOLV_NETWORK);
1284 menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Name Resolution/Enable for Transport Layer");
1285 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), g_resolv_flags & RESOLV_TRANSPORT);
1289 name_resolution_mac_cb(GtkWidget *w _U_, gpointer d _U_)
1291 if (GTK_CHECK_MENU_ITEM(w)->active) {
1292 g_resolv_flags |= RESOLV_MAC;
1294 g_resolv_flags &= ~RESOLV_MAC;
1299 name_resolution_network_cb(GtkWidget *w _U_, gpointer d _U_)
1301 if (GTK_CHECK_MENU_ITEM(w)->active) {
1302 g_resolv_flags |= RESOLV_NETWORK;
1304 g_resolv_flags &= ~RESOLV_NETWORK;
1309 name_resolution_transport_cb(GtkWidget *w _U_, gpointer d _U_)
1311 if (GTK_CHECK_MENU_ITEM(w)->active) {
1312 g_resolv_flags |= RESOLV_TRANSPORT;
1314 g_resolv_flags &= ~RESOLV_TRANSPORT;
1320 auto_scroll_live_cb(GtkWidget *w _U_, gpointer d _U_)
1322 auto_scroll_live = GTK_CHECK_MENU_ITEM(w)->active;
1326 /* the recent file read has finished, update the menu corresponding */
1328 menu_recent_read_finished(void) {
1329 GtkWidget *menu = NULL;
1331 menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Main Toolbar");
1332 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), recent.main_toolbar_show);
1334 menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Filter Toolbar");
1335 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), recent.filter_toolbar_show);
1337 menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Statusbar");
1338 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), recent.statusbar_show);
1340 menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Packet List");
1341 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), recent.packet_list_show);
1343 menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Packet Details");
1344 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), recent.tree_view_show);
1346 menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Packet Bytes");
1347 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), recent.byte_view_show);
1349 menu_name_resolution_changed();
1352 menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Auto Scroll in Live Capture");
1353 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), auto_scroll_live);
1356 main_widgets_rearrange();
1358 /* don't change the time format, if we had a command line value */
1359 if (get_timestamp_setting() != TS_NOT_SET) {
1360 recent.gui_time_format = get_timestamp_setting();
1363 switch(recent.gui_time_format) {
1365 menu = gtk_item_factory_get_widget(main_menu_factory,
1366 "/View/Time Display Format/Time of Day");
1367 /* set_active will not trigger the callback when activating an active item! */
1368 recent.gui_time_format = -1;
1369 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), FALSE);
1370 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), TRUE);
1372 case(TS_ABSOLUTE_WITH_DATE):
1373 menu = gtk_item_factory_get_widget(main_menu_factory,
1374 "/View/Time Display Format/Date and Time of Day");
1375 recent.gui_time_format = -1;
1376 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), TRUE);
1379 menu = gtk_item_factory_get_widget(main_menu_factory,
1380 "/View/Time Display Format/Seconds Since Beginning of Capture");
1381 recent.gui_time_format = -1;
1382 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), TRUE);
1385 menu = gtk_item_factory_get_widget(main_menu_factory,
1386 "/View/Time Display Format/Seconds Since Previous Packet");
1387 recent.gui_time_format = -1;
1388 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), TRUE);
1391 g_assert_not_reached();
1397 popup_menu_handler(GtkWidget *widget, GdkEvent *event, gpointer data)
1399 GtkWidget *menu = (GtkWidget *)data;
1400 GdkEventButton *event_button = NULL;
1403 if(widget == NULL || event == NULL || data == NULL) {
1408 * If we ever want to make the menu differ based on what row
1409 * and/or column we're above, we'd use "eth_clist_get_selection_info()"
1410 * to find the row and column number for the coordinates; a CTree is,
1411 * I guess, like a CList with one column(?) and the expander widget
1414 /* Check if we are on packet_list object */
1415 if (widget == OBJECT_GET_DATA(popup_menu_object, E_MPACKET_LIST_KEY)) {
1416 if (packet_list_get_event_row_column(widget, (GdkEventButton *)event,
1418 OBJECT_SET_DATA(popup_menu_object, E_MPACKET_LIST_ROW_KEY,
1419 GINT_TO_POINTER(row));
1420 OBJECT_SET_DATA(popup_menu_object, E_MPACKET_LIST_COL_KEY,
1421 GINT_TO_POINTER(column));
1422 packet_list_set_selected_row(row);
1426 /* Check if we are on tree_view object */
1427 if (widget == tree_view) {
1428 tree_view_select(widget, (GdkEventButton *) event);
1431 /* Check if we are on byte_view object */
1432 if(widget == get_notebook_bv_ptr(byte_nb_ptr)) {
1433 byte_view_select(widget, (GdkEventButton *) event);
1436 /* context menu handler (but the byte view notebook pages have their own handler) */
1437 if(event->type == GDK_BUTTON_PRESS && widget != byte_nb_ptr) {
1438 event_button = (GdkEventButton *) event;
1440 /* To qoute the "Gdk Event Structures" doc:
1441 * "Normally button 1 is the left mouse button, 2 is the middle button, and 3 is the right button" */
1442 if(event_button->button == 3) {
1443 gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL,
1444 event_button->button,
1445 event_button->time);
1446 SIGNAL_EMIT_STOP_BY_NAME(widget, "button_press_event");
1450 #if GTK_MAJOR_VERSION >= 2
1451 /* GDK_2BUTTON_PRESS is a doubleclick -> expand/collapse tree row */
1452 /* GTK version 1 seems to be doing this automatically */
1453 if (widget == tree_view && event->type == GDK_2BUTTON_PRESS) {
1456 if (gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(widget),
1457 (gint) (((GdkEventButton *)event)->x),
1458 (gint) (((GdkEventButton *)event)->y),
1459 &path, NULL, NULL, NULL))
1461 if (gtk_tree_view_row_expanded(GTK_TREE_VIEW(widget), path))
1462 gtk_tree_view_collapse_row(GTK_TREE_VIEW(widget), path);
1464 gtk_tree_view_expand_row(GTK_TREE_VIEW(widget), path,
1466 gtk_tree_path_free(path);
1473 /* Enable or disable menu items based on whether you have a capture file
1474 you've finished reading. */
1476 set_menus_for_capture_file(gboolean have_capture_file)
1478 set_menu_sensitivity(main_menu_factory, "/File/Open...", have_capture_file);
1479 set_menu_sensitivity(main_menu_factory, "/File/Open Recent", have_capture_file);
1480 set_menu_sensitivity(main_menu_factory, "/File/Merge...", have_capture_file);
1481 set_menu_sensitivity(main_menu_factory, "/File/Close", have_capture_file);
1482 set_menu_sensitivity(main_menu_factory, "/File/Save As...",
1484 set_menu_sensitivity(main_menu_factory, "/File/Export", have_capture_file);
1485 set_menu_sensitivity(main_menu_factory, "/View/Reload", have_capture_file);
1486 set_toolbar_for_capture_file(have_capture_file);
1487 packets_bar_update();
1490 /* Enable or disable menu items based on whether you have an unsaved
1491 capture file you've finished reading. */
1493 set_menus_for_unsaved_capture_file(gboolean have_unsaved_capture_file)
1495 set_menu_sensitivity(main_menu_factory, "/File/Save",
1496 have_unsaved_capture_file);
1497 set_toolbar_for_unsaved_capture_file(have_unsaved_capture_file);
1500 /* Enable or disable menu items based on whether there's a capture in
1503 set_menus_for_capture_in_progress(gboolean capture_in_progress)
1505 set_menu_sensitivity(main_menu_factory, "/File/Open...",
1506 !capture_in_progress);
1507 set_menu_sensitivity(main_menu_factory, "/File/Open Recent",
1508 !capture_in_progress);
1510 set_menu_sensitivity(main_menu_factory, "/Capture/Start...",
1511 !capture_in_progress);
1512 set_menu_sensitivity(main_menu_factory, "/Capture/Stop",
1513 capture_in_progress);
1514 #endif /* HAVE_LIBPCAP */
1515 set_toolbar_for_capture_in_progress(capture_in_progress);
1517 set_capture_if_dialog_for_capture_in_progress(capture_in_progress);
1520 /* Enable or disable menu items based on whether you have some captured
1523 walk_menu_tree_for_captured_packets(GList *node,
1524 gboolean have_captured_packets)
1526 gboolean is_enabled;
1528 menu_item_t *node_data = node->data;
1531 * Is this a leaf node or an interior node?
1533 if (node_data->children == NULL) {
1537 * If it has no "selected_packet_enabled()" or
1538 * "selected_tree_row_enabled()" routines, we enable
1539 * it. This allows tap windows to be popped up even
1540 * if you have no capture file; this is done to let
1541 * the user pop up multiple tap windows before reading
1542 * in a capture file, so that they can be processed in
1543 * parallel while the capture file is being read rather
1544 * than one at at time as you pop up the windows, and to
1545 * let the user pop up tap windows before starting an
1546 * "Update list of packets in real time" capture, so that
1547 * the statistics can be displayed while the capture is
1550 * If it has either of those routines, we disable it for
1551 * now - as long as, when a capture is first available,
1552 * we don't get called after a packet or tree row is
1553 * selected, that's OK.
1554 * XXX - that should be done better.
1556 if (node_data->selected_packet_enabled == NULL &&
1557 node_data->selected_tree_row_enabled == NULL)
1558 node_data->enabled = TRUE;
1560 node_data->enabled = FALSE;
1563 * It's an interior node; call
1564 * "walk_menu_tree_for_captured_packets()" on all its
1565 * children and, if any of them are enabled, enable
1566 * this node, otherwise disable it.
1568 * XXX - should we just leave all interior nodes enabled?
1569 * Which is a better UI choice?
1572 for (child = node_data->children; child != NULL; child =
1574 if (walk_menu_tree_for_captured_packets(child,
1575 have_captured_packets))
1578 node_data->enabled = is_enabled;
1582 * The root node doesn't correspond to a menu tree item; it
1583 * has a null name pointer.
1585 if (node_data->name != NULL) {
1586 set_menu_sensitivity(main_menu_factory, node_data->name,
1587 node_data->enabled);
1589 return node_data->enabled;
1593 set_menus_for_captured_packets(gboolean have_captured_packets)
1595 set_menu_sensitivity(main_menu_factory, "/File/Print...",
1596 have_captured_packets);
1597 set_menu_sensitivity(packet_list_menu_factory, "/Print...",
1598 have_captured_packets);
1599 set_menu_sensitivity(main_menu_factory, "/Edit/Find Packet...",
1600 have_captured_packets);
1601 set_menu_sensitivity(main_menu_factory, "/Edit/Find Next",
1602 have_captured_packets);
1603 set_menu_sensitivity(main_menu_factory, "/Edit/Find Previous",
1604 have_captured_packets);
1605 set_menu_sensitivity(main_menu_factory, "/View/Zoom In",
1606 have_captured_packets);
1607 set_menu_sensitivity(main_menu_factory, "/View/Zoom Out",
1608 have_captured_packets);
1609 set_menu_sensitivity(main_menu_factory, "/View/Normal Size",
1610 have_captured_packets);
1611 set_menu_sensitivity(packet_list_menu_factory, "/Coloring Rules...",
1612 have_captured_packets);
1613 set_menu_sensitivity(main_menu_factory, "/Go/Go to Packet...",
1614 have_captured_packets);
1615 set_menu_sensitivity(main_menu_factory, "/Go/First Packet",
1616 have_captured_packets);
1617 set_menu_sensitivity(main_menu_factory, "/Go/Last Packet",
1618 have_captured_packets);
1619 set_menu_sensitivity(main_menu_factory, "/Statistics/Summary",
1620 have_captured_packets);
1621 set_menu_sensitivity(main_menu_factory, "/Statistics/Protocol Hierarchy",
1622 have_captured_packets);
1624 walk_menu_tree_for_captured_packets(tap_menu_tree_root,
1625 have_captured_packets);
1626 set_toolbar_for_captured_packets(have_captured_packets);
1627 packets_bar_update();
1630 /* Enable or disable menu items based on whether a packet is selected and,
1631 if so, on the properties of the packet. */
1633 walk_menu_tree_for_selected_packet(GList *node, frame_data *fd,
1634 epan_dissect_t *edt)
1636 gboolean is_enabled;
1638 menu_item_t *node_data = node->data;
1641 * Is this a leaf node or an interior node?
1643 if (node_data->children == NULL) {
1647 * If it has no "selected_packet_enabled()" routine,
1648 * leave its enabled/disabled status alone - it
1649 * doesn't depend on whether we have a packet selected
1650 * or not or on the selected packet.
1652 * If it has a "selected_packet_enabled()" routine,
1653 * call it and set the item's enabled/disabled status
1654 * based on its return value.
1656 if (node_data->selected_packet_enabled != NULL)
1657 node_data->enabled = node_data->selected_packet_enabled(fd, edt);
1660 * It's an interior node; call
1661 * "walk_menu_tree_for_selected_packet()" on all its
1662 * children and, if any of them are enabled, enable
1663 * this node, otherwise disable it.
1665 * XXX - should we just leave all interior nodes enabled?
1666 * Which is a better UI choice?
1669 for (child = node_data->children; child != NULL; child =
1671 if (walk_menu_tree_for_selected_packet(child, fd, edt))
1674 node_data->enabled = is_enabled;
1678 * The root node doesn't correspond to a menu tree item; it
1679 * has a null name pointer.
1681 if (node_data->name != NULL) {
1682 set_menu_sensitivity(main_menu_factory, node_data->name,
1683 node_data->enabled);
1685 return node_data->enabled;
1689 set_menus_for_selected_packet(capture_file *cf)
1691 set_menu_sensitivity(main_menu_factory, "/Edit/Mark Packet",
1692 cf->current_frame != NULL);
1693 set_menu_sensitivity(packet_list_menu_factory, "/Mark Packet",
1694 cf->current_frame != NULL);
1695 set_menu_sensitivity(main_menu_factory, "/Edit/Time Reference",
1696 cf->current_frame != NULL);
1697 set_menu_sensitivity(packet_list_menu_factory, "/Time Reference",
1698 cf->current_frame != NULL);
1699 set_menu_sensitivity(main_menu_factory, "/Edit/Mark All Packets",
1700 cf->current_frame != NULL);
1701 set_menu_sensitivity(main_menu_factory, "/Edit/Unmark All Packets",
1702 cf->current_frame != NULL);
1703 set_menu_sensitivity(main_menu_factory, "/View/Collapse All",
1704 cf->current_frame != NULL);
1705 set_menu_sensitivity(tree_view_menu_factory, "/Collapse All",
1706 cf->current_frame != NULL);
1707 set_menu_sensitivity(main_menu_factory, "/View/Expand All",
1708 cf->current_frame != NULL);
1709 set_menu_sensitivity(tree_view_menu_factory, "/Expand All",
1710 cf->current_frame != NULL);
1711 set_menu_sensitivity(main_menu_factory, "/View/Show Packet in New Window",
1712 cf->current_frame != NULL);
1713 set_menu_sensitivity(packet_list_menu_factory, "/Show Packet in New Window",
1714 cf->current_frame != NULL);
1715 set_menu_sensitivity(main_menu_factory, "/Analyze/Follow TCP Stream",
1716 cf->current_frame != NULL ? (cf->edt->pi.ipproto == IP_PROTO_TCP) : FALSE);
1717 set_menu_sensitivity(NULL, "/Follow TCP Stream",
1718 cf->current_frame != NULL ? (cf->edt->pi.ipproto == IP_PROTO_TCP) : FALSE);
1719 set_menu_sensitivity(main_menu_factory, "/Analyze/Decode As...",
1720 cf->current_frame != NULL && decode_as_ok());
1721 set_menu_sensitivity(NULL, "/Decode As...",
1722 cf->current_frame != NULL && decode_as_ok());
1723 set_menu_sensitivity(main_menu_factory, "/View/Name Resolution/Resolve Name",
1724 cf->current_frame != NULL && (g_resolv_flags & RESOLV_ALL_ADDRS) != RESOLV_ALL_ADDRS);
1725 set_menu_sensitivity(tree_view_menu_factory, "/Resolve Name",
1726 cf->current_frame != NULL && (g_resolv_flags & RESOLV_ALL_ADDRS) != RESOLV_ALL_ADDRS);
1727 set_menu_sensitivity(packet_list_menu_factory, "/Apply as Filter",
1728 cf->current_frame != NULL);
1729 set_menu_sensitivity(packet_list_menu_factory, "/Prepare a Filter",
1730 cf->current_frame != NULL);
1732 walk_menu_tree_for_selected_packet(tap_menu_tree_root, cf->current_frame,
1734 packets_bar_update();
1737 /* Enable or disable menu items based on whether a tree row is selected
1738 and, if so, on the properties of the tree row. */
1740 walk_menu_tree_for_selected_tree_row(GList *node, field_info *fi)
1742 gboolean is_enabled;
1744 menu_item_t *node_data = node->data;
1747 * Is this a leaf node or an interior node?
1749 if (node_data->children == NULL) {
1753 * If it has no "selected_tree_row_enabled()" routine,
1754 * leave its enabled/disabled status alone - it
1755 * doesn't depend on whether we have a tree row selected
1756 * or not or on the selected tree row.
1758 * If it has a "selected_tree_row_enabled()" routine,
1759 * call it and set the item's enabled/disabled status
1760 * based on its return value.
1762 if (node_data->selected_tree_row_enabled != NULL)
1763 node_data->enabled = node_data->selected_tree_row_enabled(fi);
1766 * It's an interior node; call
1767 * "walk_menu_tree_for_selected_tree_row()" on all its
1768 * children and, if any of them are enabled, enable
1769 * this node, otherwise disable it.
1771 * XXX - should we just leave all interior nodes enabled?
1772 * Which is a better UI choice?
1775 for (child = node_data->children; child != NULL; child =
1777 if (walk_menu_tree_for_selected_tree_row(child, fi))
1780 node_data->enabled = is_enabled;
1784 * The root node doesn't correspond to a menu tree item; it
1785 * has a null name pointer.
1787 if (node_data->name != NULL) {
1788 set_menu_sensitivity(main_menu_factory, node_data->name,
1789 node_data->enabled);
1791 return node_data->enabled;
1795 set_menus_for_selected_tree_row(capture_file *cf)
1797 gboolean properties;
1800 set_menu_sensitivity(main_menu_factory, "/File/Export/Selected Packet Bytes...",
1801 cf->finfo_selected != NULL);
1802 set_menu_sensitivity(tree_view_menu_factory, "/Export Selected Packet Bytes...",
1803 cf->finfo_selected != NULL);
1804 set_menu_sensitivity(hexdump_menu_factory, "/Export Selected Packet Bytes...",
1805 cf->finfo_selected != NULL);
1807 if (cf->finfo_selected != NULL) {
1808 header_field_info *hfinfo = cf->finfo_selected->hfinfo;
1809 if (hfinfo->parent == -1) {
1810 properties = prefs_is_registered_protocol(hfinfo->abbrev);
1812 properties = prefs_is_registered_protocol(proto_registrar_get_abbrev(hfinfo->parent));
1814 set_menu_sensitivity(main_menu_factory,
1815 "/Go/Go to Corresponding Packet", hfinfo->type == FT_FRAMENUM);
1816 set_menu_sensitivity(tree_view_menu_factory,
1817 "/Go to Corresponding Packet", hfinfo->type == FT_FRAMENUM);
1818 set_menu_sensitivity(main_menu_factory, "/Analyze/Apply as Filter",
1819 proto_can_match_selected(cf->finfo_selected, cf->edt));
1820 set_menu_sensitivity(tree_view_menu_factory, "/Apply as Filter",
1821 proto_can_match_selected(cf->finfo_selected, cf->edt));
1822 set_menu_sensitivity(main_menu_factory, "/Analyze/Prepare a Filter",
1823 proto_can_match_selected(cf->finfo_selected, cf->edt));
1824 set_menu_sensitivity(tree_view_menu_factory, "/Prepare a Filter",
1825 proto_can_match_selected(cf->finfo_selected, cf->edt));
1826 set_menu_sensitivity(tree_view_menu_factory, "/Protocol Preferences...",
1828 set_menu_sensitivity(main_menu_factory, "/View/Expand Tree", cf->finfo_selected->tree_type != -1);
1829 set_menu_sensitivity(tree_view_menu_factory, "/Expand Tree", cf->finfo_selected->tree_type != -1);
1831 set_menu_sensitivity(main_menu_factory,
1832 "/Go/Go to Corresponding Packet", FALSE);
1833 set_menu_sensitivity(tree_view_menu_factory,
1834 "/Go to Corresponding Packet", FALSE);
1835 set_menu_sensitivity(main_menu_factory, "/Analyze/Apply as Filter", FALSE);
1836 set_menu_sensitivity(tree_view_menu_factory, "/Apply as Filter", FALSE);
1837 set_menu_sensitivity(main_menu_factory, "/Analyze/Prepare a Filter", FALSE);
1838 set_menu_sensitivity(tree_view_menu_factory, "/Prepare a Filter", FALSE);
1839 set_menu_sensitivity(tree_view_menu_factory, "/Protocol Preferences...",
1841 set_menu_sensitivity(main_menu_factory, "/View/Expand Tree", FALSE);
1842 set_menu_sensitivity(tree_view_menu_factory, "/Expand Tree", FALSE);
1845 walk_menu_tree_for_selected_tree_row(tap_menu_tree_root, cf->finfo_selected);