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 #ifdef ETHEREAL_EUG_DIR
347 ITEM_FACTORY_ENTRY("/Help/User's Guide", NULL, url_page_menu_cb, HELP_CONTENT, NULL, NULL),
349 ITEM_FACTORY_ENTRY("/Help/Manual Pages", NULL, NULL, 0, "<Branch>", NULL),
350 ITEM_FACTORY_ENTRY("/Help/Manual Pages/Ethereal", NULL, url_page_menu_cb, LOCALPAGE_MAN_ETHEREAL, NULL, NULL),
351 ITEM_FACTORY_ENTRY("/Help/Manual Pages/Ethereal Filter", NULL, url_page_menu_cb, LOCALPAGE_MAN_ETHEREAL_FILTER, NULL, NULL),
352 ITEM_FACTORY_ENTRY("/Help/Manual Pages/<separator>", NULL, NULL, 0, "<Separator>", NULL),
353 ITEM_FACTORY_ENTRY("/Help/Manual Pages/Tethereal", NULL, url_page_menu_cb, LOCALPAGE_MAN_TETHEREAL, NULL, NULL),
354 ITEM_FACTORY_ENTRY("/Help/Manual Pages/Mergecap", NULL, url_page_menu_cb, LOCALPAGE_MAN_MERGECAP, NULL, NULL),
355 ITEM_FACTORY_ENTRY("/Help/Manual Pages/Editcap", NULL, url_page_menu_cb, LOCALPAGE_MAN_EDITCAP, NULL, NULL),
356 ITEM_FACTORY_ENTRY("/Help/Manual Pages/Text2pcap", NULL, url_page_menu_cb, LOCALPAGE_MAN_TEXT2PCAP, NULL, NULL),
357 ITEM_FACTORY_ENTRY("/Help/Ethereal Online", NULL, NULL, 0, "<Branch>", NULL),
358 ITEM_FACTORY_STOCK_ENTRY("/Help/Ethereal Online/Home Page", NULL, url_page_menu_cb, ONLINEPAGE_HOME, GTK_STOCK_HOME),
359 ITEM_FACTORY_ENTRY("/Help/Ethereal Online/User's Guide", NULL, url_page_menu_cb, ONLINEPAGE_USERGUIDE, NULL, NULL),
360 ITEM_FACTORY_ENTRY("/Help/Ethereal Online/FAQ's", NULL, url_page_menu_cb, ONLINEPAGE_FAQ, NULL, NULL),
361 ITEM_FACTORY_ENTRY("/Help/Ethereal Online/Downloads", NULL, url_page_menu_cb, ONLINEPAGE_DOWNLOAD, NULL, NULL),
362 ITEM_FACTORY_ENTRY("/Help/Ethereal Online/Example Files", NULL, url_page_menu_cb, ONLINEPAGE_SAMPLE_FILES, NULL, NULL),
364 ITEM_FACTORY_ENTRY("/Help/<separator>", NULL, NULL, 0, "<Separator>", NULL),
365 ITEM_FACTORY_ENTRY("/Help/_About Ethereal", NULL, about_ethereal_cb,
370 /* calculate the number of menu_items */
371 static int nmenu_items = sizeof(menu_items) / sizeof(menu_items[0]);
373 /* packet list popup */
374 static GtkItemFactoryEntry packet_list_menu_items[] =
376 ITEM_FACTORY_ENTRY("/Follow TCP Stream", NULL, follow_stream_cb,
378 ITEM_FACTORY_ENTRY("/Decode As...", NULL, decode_as_cb, 0, NULL, NULL),
379 ITEM_FACTORY_ENTRY("/Display Filters...", NULL, dfilter_dialog_cb,
381 ITEM_FACTORY_ENTRY("/<separator>", NULL, NULL, 0, "<Separator>", NULL),
382 ITEM_FACTORY_ENTRY("/Mark Packet", NULL, mark_frame_cb, 0, NULL, NULL),
383 ITEM_FACTORY_ENTRY("/Time Reference", NULL, NULL, 0, "<Branch>", NULL),
384 ITEM_FACTORY_ENTRY("/Time Reference/Set Time Reference (toggle)", NULL, reftime_frame_cb, REFTIME_TOGGLE, NULL, NULL),
385 ITEM_FACTORY_ENTRY("/Time Reference/Find Next", NULL, reftime_frame_cb, REFTIME_FIND_NEXT, NULL, NULL),
386 ITEM_FACTORY_ENTRY("/Time Reference/Find Previous", NULL, reftime_frame_cb, REFTIME_FIND_PREV, NULL, NULL),
387 ITEM_FACTORY_ENTRY("/Apply as Filter", NULL, NULL, 0, "<Branch>", NULL),
388 ITEM_FACTORY_ENTRY("/Apply as Filter/_Selected", NULL, match_selected_plist_cb,
389 MATCH_SELECTED_REPLACE|MATCH_SELECTED_APPLY_NOW, NULL, NULL),
390 ITEM_FACTORY_ENTRY("/Apply as Filter/_Not Selected", NULL, match_selected_plist_cb,
391 MATCH_SELECTED_NOT|MATCH_SELECTED_APPLY_NOW, NULL, NULL),
392 ITEM_FACTORY_ENTRY("/Apply as Filter/... _and Selected", NULL, match_selected_plist_cb,
393 MATCH_SELECTED_AND|MATCH_SELECTED_APPLY_NOW, NULL, NULL),
394 ITEM_FACTORY_ENTRY("/Apply as Filter/... _or Selected", NULL, match_selected_plist_cb,
395 MATCH_SELECTED_OR|MATCH_SELECTED_APPLY_NOW, NULL, NULL),
396 ITEM_FACTORY_ENTRY("/Apply as Filter/... a_nd not Selected", NULL, match_selected_plist_cb,
397 MATCH_SELECTED_AND_NOT|MATCH_SELECTED_APPLY_NOW, NULL, NULL),
398 ITEM_FACTORY_ENTRY("/Apply as Filter/... o_r not Selected", NULL, match_selected_plist_cb,
399 MATCH_SELECTED_OR_NOT|MATCH_SELECTED_APPLY_NOW, NULL, NULL),
401 ITEM_FACTORY_ENTRY("/Prepare a Filter", NULL, NULL, 0, "<Branch>", NULL),
402 ITEM_FACTORY_ENTRY("/Prepare a Filter/_Selected", NULL, match_selected_plist_cb,
403 MATCH_SELECTED_REPLACE, NULL, NULL),
404 ITEM_FACTORY_ENTRY("/Prepare a Filter/_Not Selected", NULL, match_selected_plist_cb,
405 MATCH_SELECTED_NOT, NULL, NULL),
406 ITEM_FACTORY_ENTRY("/Prepare a Filter/... _and Selected", NULL, match_selected_plist_cb,
407 MATCH_SELECTED_AND, NULL, NULL),
408 ITEM_FACTORY_ENTRY("/Prepare a Filter/... _or Selected", NULL, match_selected_plist_cb,
409 MATCH_SELECTED_OR, NULL, NULL),
410 ITEM_FACTORY_ENTRY("/Prepare a Filter/... a_nd not Selected", NULL, match_selected_plist_cb,
411 MATCH_SELECTED_AND_NOT, NULL, NULL),
412 ITEM_FACTORY_ENTRY("/Prepare a Filter/... o_r not Selected", NULL, match_selected_plist_cb,
413 MATCH_SELECTED_OR_NOT, NULL, NULL),
415 ITEM_FACTORY_ENTRY("/<separator>", NULL, NULL, 0, "<Separator>", NULL),
416 ITEM_FACTORY_ENTRY("/Coloring Rules...", NULL, color_display_cb,
418 ITEM_FACTORY_ENTRY("/Print...", NULL, file_print_cmd_cb, 0, NULL, NULL),
419 ITEM_FACTORY_ENTRY("/Show Packet in New Window", NULL, new_window_cb,
423 static GtkItemFactoryEntry tree_view_menu_items[] =
425 ITEM_FACTORY_ENTRY("/Follow TCP Stream", NULL, follow_stream_cb,
427 ITEM_FACTORY_ENTRY("/Decode As...", NULL, decode_as_cb, 0, NULL, NULL),
428 ITEM_FACTORY_ENTRY("/Display Filters...", NULL, dfilter_dialog_cb,
430 ITEM_FACTORY_ENTRY("/<separator>", NULL, NULL, 0, "<Separator>", NULL),
431 ITEM_FACTORY_ENTRY("/_Resolve Name", NULL, resolve_name_cb, 0, NULL, NULL),
432 ITEM_FACTORY_ENTRY("/_Go to Corresponding Packet", NULL, goto_framenum_cb, 0, NULL, NULL),
433 ITEM_FACTORY_ENTRY("/_Export Selected Packet Bytes...", NULL, savehex_cb,
435 ITEM_FACTORY_ENTRY("/Protocol Preferences...", NULL, properties_cb,
437 ITEM_FACTORY_ENTRY("/Apply as Filter", NULL, NULL, 0, "<Branch>", NULL),
438 ITEM_FACTORY_ENTRY("/Apply as Filter/_Selected", NULL, match_selected_ptree_cb,
439 MATCH_SELECTED_REPLACE|MATCH_SELECTED_APPLY_NOW, NULL, NULL),
440 ITEM_FACTORY_ENTRY("/Apply as Filter/_Not Selected", NULL, match_selected_ptree_cb,
441 MATCH_SELECTED_NOT|MATCH_SELECTED_APPLY_NOW, NULL, NULL),
442 ITEM_FACTORY_ENTRY("/Apply as Filter/... _and Selected", NULL, match_selected_ptree_cb,
443 MATCH_SELECTED_AND|MATCH_SELECTED_APPLY_NOW, NULL, NULL),
444 ITEM_FACTORY_ENTRY("/Apply as Filter/... _or Selected", NULL, match_selected_ptree_cb,
445 MATCH_SELECTED_OR|MATCH_SELECTED_APPLY_NOW, NULL, NULL),
446 ITEM_FACTORY_ENTRY("/Apply as Filter/... a_nd not Selected", NULL, match_selected_ptree_cb,
447 MATCH_SELECTED_AND_NOT|MATCH_SELECTED_APPLY_NOW, NULL, NULL),
448 ITEM_FACTORY_ENTRY("/Apply as Filter/... o_r not Selected", NULL, match_selected_ptree_cb,
449 MATCH_SELECTED_OR_NOT|MATCH_SELECTED_APPLY_NOW, NULL, NULL),
451 ITEM_FACTORY_ENTRY("/Prepare a Filter", NULL, NULL, 0, "<Branch>", NULL),
452 ITEM_FACTORY_ENTRY("/Prepare a Filter/_Selected", NULL, match_selected_ptree_cb,
453 MATCH_SELECTED_REPLACE, NULL, NULL),
454 ITEM_FACTORY_ENTRY("/Prepare a Filter/_Not Selected", NULL, match_selected_ptree_cb,
455 MATCH_SELECTED_NOT, NULL, NULL),
456 ITEM_FACTORY_ENTRY("/Prepare a Filter/... _and Selected", NULL, match_selected_ptree_cb,
457 MATCH_SELECTED_AND, NULL, NULL),
458 ITEM_FACTORY_ENTRY("/Prepare a Filter/... _or Selected", NULL, match_selected_ptree_cb,
459 MATCH_SELECTED_OR, NULL, NULL),
460 ITEM_FACTORY_ENTRY("/Prepare a Filter/... a_nd not Selected", NULL, match_selected_ptree_cb,
461 MATCH_SELECTED_AND_NOT, NULL, NULL),
462 ITEM_FACTORY_ENTRY("/Prepare a Filter/... o_r not Selected", NULL, match_selected_ptree_cb,
463 MATCH_SELECTED_OR_NOT, NULL, NULL),
464 ITEM_FACTORY_ENTRY("/<separator>", NULL, NULL, 0, "<Separator>", NULL),
465 ITEM_FACTORY_ENTRY("/Collapse All", NULL, collapse_all_cb, 0, NULL, NULL),
466 ITEM_FACTORY_ENTRY("/Expand All", NULL, expand_all_cb, 0, NULL, NULL),
467 ITEM_FACTORY_ENTRY("/Expand Tree", NULL, expand_tree_cb, 0, NULL, NULL)
470 static GtkItemFactoryEntry hexdump_menu_items[] =
472 ITEM_FACTORY_ENTRY("/Follow TCP Stream", NULL, follow_stream_cb,
474 ITEM_FACTORY_ENTRY("/Decode As...", NULL, decode_as_cb, 0, NULL, NULL),
475 ITEM_FACTORY_ENTRY("/Display Filters...", NULL, dfilter_dialog_cb,
477 ITEM_FACTORY_ENTRY("/Export Selected Packet Bytes...", NULL, savehex_cb,
479 ITEM_FACTORY_ENTRY("/Copy Packet Bytes into Clipboard", NULL, copy_hex_cb,
483 static int initialize = TRUE;
484 static GtkItemFactory *main_menu_factory = NULL;
485 static GtkItemFactory *packet_list_menu_factory = NULL;
486 static GtkItemFactory *tree_view_menu_factory = NULL;
487 static GtkItemFactory *hexdump_menu_factory = NULL;
489 static GSList *popup_menu_list = NULL;
491 static GtkAccelGroup *grp;
494 main_menu_new(GtkAccelGroup ** table) {
497 grp = gtk_accel_group_new();
502 menubar = main_menu_factory->widget;
516 packet_list_menu_factory = gtk_item_factory_new(GTK_TYPE_MENU, "<main>", NULL);
517 popup_menu_object = gtk_menu_new();
518 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);
519 OBJECT_SET_DATA(popup_menu_object, PM_PACKET_LIST_KEY,
520 packet_list_menu_factory->widget);
521 popup_menu_list = g_slist_append((GSList *)popup_menu_list, packet_list_menu_factory);
523 tree_view_menu_factory = gtk_item_factory_new(GTK_TYPE_MENU, "<main>", NULL);
524 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);
525 OBJECT_SET_DATA(popup_menu_object, PM_TREE_VIEW_KEY,
526 tree_view_menu_factory->widget);
527 popup_menu_list = g_slist_append((GSList *)popup_menu_list, tree_view_menu_factory);
529 hexdump_menu_factory = gtk_item_factory_new(GTK_TYPE_MENU, "<main>", NULL);
530 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);
531 OBJECT_SET_DATA(popup_menu_object, PM_HEXDUMP_KEY,
532 hexdump_menu_factory->widget);
533 popup_menu_list = g_slist_append((GSList *)popup_menu_list, hexdump_menu_factory);
536 main_menu_factory = gtk_item_factory_new(GTK_TYPE_MENU_BAR, "<main>", grp);
537 gtk_item_factory_create_items_ac(main_menu_factory, nmenu_items, menu_items, NULL, 2);
539 merge_all_tap_menus(tap_menu_tree_root);
541 /* Initialize enabled/disabled state of menu items */
542 set_menus_for_unsaved_capture_file(FALSE);
543 set_menus_for_capture_file(FALSE);
545 /* Un-#if this when we actually implement Cut/Copy/Paste.
546 Then make sure you enable them when they can be done. */
547 set_menu_sensitivity(main_menu_factory, "/Edit/Cut", FALSE);
548 set_menu_sensitivity(main_menu_factory, "/Edit/Copy", FALSE);
549 set_menu_sensitivity(main_menu_factory, "/Edit/Paste", FALSE);
552 set_menus_for_captured_packets(FALSE);
553 set_menus_for_selected_packet(&cfile);
554 set_menus_for_selected_tree_row(&cfile);
556 /* init with an empty recent files list */
557 clear_menu_recent_capture_file_cmd_cb(NULL, NULL);
562 gint tap_menu_item_add_compare(gconstpointer a, gconstpointer b)
565 ((const menu_item_t *) a)->name,
566 ((const menu_item_t *) b)->name);
570 /* add a menuitem below the current node */
571 GList * tap_menu_item_add(
574 GtkItemFactoryCallback callback,
575 gboolean (*selected_packet_enabled)(frame_data *, epan_dissect_t *),
576 gboolean (*selected_tree_row_enabled)(field_info *),
577 gpointer callback_data,
584 child = g_malloc(sizeof (menu_item_t));
585 child->group = group;
587 child->callback = callback;
588 child->selected_packet_enabled = selected_packet_enabled;
589 child->selected_tree_row_enabled = selected_tree_row_enabled;
590 child->callback_data = callback_data;
591 child->enabled = FALSE;
592 child->children = NULL;
594 /* insert the new child node into the parent */
595 curr = curnode->data;
596 curr->children = g_list_insert_sorted(curr->children, child, tap_menu_item_add_compare);
598 /* return the new node */
599 /* XXX: improve this */
600 return g_list_find(curr->children, child);
604 * Add a new menu item for a tap.
605 * This must be called after we've created the main menu, so it can't
606 * be called from the routine that registers taps - we have to introduce
607 * another per-tap registration routine.
609 * "callback" gets called when the menu item is selected; it should do
610 * the work of creating the tap window.
612 * "selected_packet_enabled" gets called by "set_menus_for_selected_packet()";
613 * it's passed a Boolean that's TRUE if a packet is selected and FALSE
614 * otherwise, and should return TRUE if the tap will work now (which
615 * might depend on whether a packet is selected and, if one is, on the
616 * packet) and FALSE if not.
618 * "selected_tree_row_enabled" gets called by
619 * "set_menus_for_selected_tree_row()"; it's passed a Boolean that's TRUE if
620 * a protocol tree row is selected and FALSE otherwise, and should return
621 * TRUE if the tap will work now (which might depend on whether a tree row
622 * is selected and, if one is, on the tree row) and FALSE if not.
625 register_tap_menu_item(
627 REGISTER_TAP_GROUP_E group,
628 GtkItemFactoryCallback callback,
629 gboolean (*selected_packet_enabled)(frame_data *, epan_dissect_t *),
630 gboolean (*selected_tree_row_enabled)(field_info *),
631 gpointer callback_data)
633 /*static const char toolspath[] = "/Statistics/";*/
643 * The menu path must be relative.
645 g_assert(*name != '/');
648 case(REGISTER_TAP_GROUP_GENERIC): toolspath = "/Statistics/"; break;
649 case(REGISTER_TAP_GROUP_CONVERSATION_LIST): toolspath = "/Statistics/_Conversation List/"; break;
650 case(REGISTER_TAP_GROUP_ENDPOINT_LIST): toolspath = "/Statistics/_Endpoint List/"; break;
651 case(REGISTER_TAP_GROUP_RESPONSE_TIME): toolspath = "/Statistics/Service _Response Time/"; break;
652 case(REGISTER_TAP_GROUP_NONE): toolspath = "/Statistics/"; break;
658 /* add the (empty) root node, if not already done */
659 if(tap_menu_tree_root == NULL) {
660 child = g_malloc0(sizeof (menu_item_t));
661 tap_menu_tree_root = g_list_append(NULL, child);
665 * Create any submenus required.
667 curnode = tap_menu_tree_root;
669 while ((p = strchr(p, '/')) != NULL) {
671 * OK, everything between "name" and "p" is
672 * a menu relative subtree into which the menu item
675 * Construct the absolute path name of that subtree.
677 menupathlen = strlen(toolspath) + 1 + (p - name);
678 menupath = g_malloc(menupathlen);
679 strcpy(menupath, toolspath);
680 strncat(menupath, name, p - name);
683 * Does there exist an entry with that path at this
684 * level of the Analyze menu tree?
686 child = curnode->data;
687 for (childnode = child->children; childnode != NULL; childnode = childnode->next) {
688 child = childnode->data;
689 if (strcmp(child->name, menupath) == 0)
692 if (childnode == NULL) {
694 * No. Create such an item as a subtree, and
695 * add it to the Tools menu tree.
697 childnode = tap_menu_item_add(
698 menupath, group, NULL, NULL ,NULL, NULL, curnode);
701 * Yes. We don't need this "menupath" any longer.
708 * Skip over the '/' we found.
714 * Construct the main menu path for the menu item.
716 menupathlen = strlen(toolspath) + 1 + strlen(name);
717 menupath = g_malloc(menupathlen);
718 strcpy(menupath, toolspath);
719 strcat(menupath, name);
722 * Construct an item factory entry for the item, and add it to
726 menupath, group, callback,
727 selected_packet_enabled, selected_tree_row_enabled,
728 callback_data, curnode);
732 guint merge_tap_menus_layered(GList *node, gint group) {
733 GtkItemFactoryEntry *entry;
736 menu_item_t *node_data = node->data;
739 * Is this a leaf node or an interior node?
741 if (node_data->children == NULL) {
747 * The root node doesn't correspond to a menu tree item; it
748 * has a null name pointer.
750 if (node_data->name != NULL && group == node_data->group) {
751 entry = g_malloc0(sizeof (GtkItemFactoryEntry));
752 entry->path = node_data->name;
753 entry->callback = node_data->callback;
754 gtk_item_factory_create_item(main_menu_factory, entry, node_data->callback_data, 2);
755 set_menu_sensitivity(main_menu_factory, node_data->name, FALSE); /* no capture file yet */
760 * It's an interior node; call
761 * "merge_tap_menus_layered()" on all its children
765 * The root node doesn't correspond to a menu tree item; it
766 * has a null name pointer.
768 if (node_data->name != NULL && group == node_data->group) {
769 entry = g_malloc0(sizeof (GtkItemFactoryEntry));
770 entry->path = node_data->name;
771 entry->item_type = "<Branch>";
772 gtk_item_factory_create_item(main_menu_factory, entry,
774 set_menu_sensitivity(main_menu_factory, node_data->name,
775 FALSE); /* no children yet */
779 for (child = node_data->children; child != NULL; child =
781 added += merge_tap_menus_layered(child, group);
789 void merge_all_tap_menus(GList *node) {
790 GtkItemFactoryEntry *entry;
792 entry = g_malloc0(sizeof (GtkItemFactoryEntry));
793 entry->item_type = "<Separator>";
794 entry->path = "/Statistics/";
797 * merge only the menu items of the specific group,
798 * and then append a seperator
800 if (merge_tap_menus_layered(node, REGISTER_TAP_GROUP_GENERIC)) {
801 gtk_item_factory_create_item(main_menu_factory, entry, NULL, 2);
803 if (merge_tap_menus_layered(node, REGISTER_TAP_GROUP_CONVERSATION_LIST)) {
804 /*gtk_item_factory_create_item(main_menu_factory, entry, NULL, 2);*/
806 if (merge_tap_menus_layered(node, REGISTER_TAP_GROUP_ENDPOINT_LIST)) {
807 /*gtk_item_factory_create_item(main_menu_factory, entry, NULL, 2);*/
809 if (merge_tap_menus_layered(node, REGISTER_TAP_GROUP_RESPONSE_TIME)) {
810 gtk_item_factory_create_item(main_menu_factory, entry, NULL, 2);
812 if (merge_tap_menus_layered(node, REGISTER_TAP_GROUP_NONE)) {
813 /*gtk_item_factory_create_item(main_menu_factory, entry, NULL, 2);*/
820 * Enable/disable menu sensitivity.
823 set_menu_sensitivity(GtkItemFactory *ifactory, const gchar *path, gint val)
826 GtkWidget *menu_item;
831 /* the underscore character regularly confuses things, as it will prevent finding
832 * the menu_item, so it has to be removed first */
833 dup = g_strdup(path);
844 if (ifactory == NULL) {
846 * Do it for all pop-up menus.
848 for (menu_list = popup_menu_list; menu_list != NULL;
849 menu_list = g_slist_next(menu_list))
850 set_menu_sensitivity(menu_list->data, dup, val);
853 * Do it for that particular menu.
855 if ((menu_item = gtk_item_factory_get_widget(ifactory, dup)) != NULL) {
856 if (GTK_IS_MENU(menu_item)) {
858 * "dup" refers to a submenu; "gtk_item_factory_get_widget()"
859 * gets the menu, not the item that, when selected, pops up
862 * We have to change the latter item's sensitivity, so that
863 * it shows up normally if sensitive and grayed-out if
866 menu_item = gtk_menu_get_attach_widget(GTK_MENU(menu_item));
868 gtk_widget_set_sensitive(menu_item, val);
870 /* be sure this menu item *is* existing */
871 g_assert_not_reached();
879 set_menu_object_data_meat(GtkItemFactory *ifactory, gchar *path, gchar *key, gpointer data)
881 GtkWidget *menu = NULL;
883 if ((menu = gtk_item_factory_get_widget(ifactory, path)) != NULL)
884 OBJECT_SET_DATA(menu, key, data);
888 set_menu_object_data (gchar *path, gchar *key, gpointer data) {
889 GSList *menu_list = popup_menu_list;
890 gchar *shortpath = strrchr(path, '/');
892 set_menu_object_data_meat(main_menu_factory, path, key, data);
893 while (menu_list != NULL) {
894 set_menu_object_data_meat(menu_list->data, shortpath, key, data);
895 menu_list = g_slist_next(menu_list);
900 /* Recently used capture files submenu:
901 * Submenu containing the recently used capture files.
902 * The capture filenames are always kept with the absolute path, to be independant
903 * of the current path.
904 * They are only stored inside the labels of the submenu (no separate list). */
906 #define MENU_RECENT_FILES_PATH "/File/Open Recent"
907 #define MENU_RECENT_FILES_KEY "Recent File Name"
910 update_menu_recent_capture_file1(GtkWidget *widget, gpointer cnt) {
911 gchar *widget_cf_name;
913 widget_cf_name = OBJECT_GET_DATA(widget, MENU_RECENT_FILES_KEY);
915 /* if this menu item is a file, count it */
916 if (widget_cf_name) {
922 /* update the menu */
924 update_menu_recent_capture_file(GtkWidget *submenu_recent_files) {
927 gtk_container_foreach(GTK_CONTAINER(submenu_recent_files),
928 update_menu_recent_capture_file1, &cnt);
930 /* make parent menu item sensitive only, if we have any valid files in the list */
931 set_menu_sensitivity(main_menu_factory, MENU_RECENT_FILES_PATH, cnt);
935 /* remove the capture filename from the "Recent Files" menu */
937 remove_menu_recent_capture_file(GtkWidget *widget, gpointer unused _U_) {
938 GtkWidget *submenu_recent_files;
939 gchar *widget_cf_name;
942 widget_cf_name = OBJECT_GET_DATA(widget, MENU_RECENT_FILES_KEY);
943 g_free(widget_cf_name);
945 /* get the submenu container item */
946 submenu_recent_files = gtk_item_factory_get_widget(main_menu_factory, MENU_RECENT_FILES_PATH);
948 /* XXX: is this all we need to do, to free the menu item and its label?
949 The reference count of widget will go to 0, so it'll be freed;
950 will that free the label? */
951 gtk_container_remove(GTK_CONTAINER(submenu_recent_files), widget);
955 /* callback, if the user pushed the <Clear File List> item */
957 clear_menu_recent_capture_file_cmd_cb(GtkWidget *w _U_, gpointer unused _U_) {
958 GtkWidget *submenu_recent_files;
961 submenu_recent_files = gtk_item_factory_get_widget(main_menu_factory, MENU_RECENT_FILES_PATH);
963 gtk_container_foreach(GTK_CONTAINER(submenu_recent_files),
964 remove_menu_recent_capture_file, NULL);
966 update_menu_recent_capture_file(submenu_recent_files);
970 /* callback, if the user pushed a recent file submenu item */
972 menu_open_recent_file_cmd(GtkWidget *w)
974 GtkWidget *submenu_recent_files;
975 GtkWidget *menu_item_child;
979 submenu_recent_files = gtk_item_factory_get_widget(main_menu_factory, MENU_RECENT_FILES_PATH);
981 /* get capture filename from the menu item label */
982 menu_item_child = (GTK_BIN(w))->child;
983 gtk_label_get(GTK_LABEL(menu_item_child), &cf_name);
985 /* open and read the capture file (this will close an existing file) */
986 if ((err = cf_open(cf_name, FALSE, &cfile)) == 0) {
989 /* the capture file isn't existing any longer, remove menu item */
990 /* XXX: ask user to remove item, it's maybe only a temporary problem */
991 remove_menu_recent_capture_file(w, NULL);
994 update_menu_recent_capture_file(submenu_recent_files);
997 static void menu_open_recent_file_answered_cb(gpointer dialog _U_, gint btn, gpointer data _U_)
1001 /* save file first */
1002 file_save_as_cmd(after_save_open_recent_file, data);
1006 menu_open_recent_file_cmd(data);
1008 case(ESD_BTN_CANCEL):
1011 g_assert_not_reached();
1016 menu_open_recent_file_cmd_cb(GtkWidget *widget, gpointer data _U_) {
1020 if((cfile.state != FILE_CLOSED) && !cfile.user_saved && prefs.gui_ask_unsaved) {
1021 /* user didn't saved his current file, ask him */
1022 dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_YES_NO_CANCEL,
1023 PRIMARY_TEXT_START "Save capture file before opening a new one?" PRIMARY_TEXT_END "\n\n"
1024 "If you open a new capture file without saving, your current capture data will be discarded.");
1025 simple_dialog_set_cb(dialog, menu_open_recent_file_answered_cb, widget);
1027 /* unchanged file */
1028 menu_open_recent_file_cmd(widget);
1032 /* add the capture filename (with an absolute path) to the "Recent Files" menu */
1034 add_menu_recent_capture_file_absolute(gchar *cf_name) {
1035 GtkWidget *submenu_recent_files;
1036 GList *menu_item_list;
1038 gchar *widget_cf_name;
1039 gchar *normalized_cf_name;
1040 GtkWidget *menu_item;
1045 normalized_cf_name = g_strdup(cf_name);
1047 /* replace all slashes by backslashes */
1048 g_strdelimit(normalized_cf_name, "/", '\\');
1051 /* get the submenu container item */
1052 submenu_recent_files = gtk_item_factory_get_widget(main_menu_factory, MENU_RECENT_FILES_PATH);
1054 /* convert container to a GList */
1055 menu_item_list = gtk_container_children(GTK_CONTAINER(submenu_recent_files));
1057 /* iterate through list items of menu_item_list,
1058 * removing special items, a maybe duplicate entry and every item above count_max */
1060 for (li = g_list_first(menu_item_list); li; li = li->next, cnt++) {
1061 /* get capture filename */
1062 menu_item = GTK_WIDGET(li->data);
1063 widget_cf_name = OBJECT_GET_DATA(menu_item, MENU_RECENT_FILES_KEY);
1065 /* if this element string is one of our special items (seperator, ...) or
1066 * already in the list or
1067 * this element is above maximum count (too old), remove it */
1068 if (!widget_cf_name ||
1070 /* do a case insensitive compare on win32 */
1071 #if GLIB_MAJOR_VERSION < 2
1072 g_strncasecmp(widget_cf_name, normalized_cf_name, 1000) == 0 ||
1074 g_ascii_strncasecmp(widget_cf_name, normalized_cf_name, 1000) == 0 ||
1077 /* do a case sensitive compare on unix */
1078 strncmp(widget_cf_name, normalized_cf_name, 1000) == 0 ||
1080 cnt >= prefs.gui_recent_files_count_max) {
1081 remove_menu_recent_capture_file(li->data, NULL);
1086 g_list_free(menu_item_list);
1088 /* add new item at latest position */
1089 menu_item = gtk_menu_item_new_with_label(normalized_cf_name);
1090 OBJECT_SET_DATA(menu_item, MENU_RECENT_FILES_KEY, normalized_cf_name);
1091 gtk_menu_prepend (GTK_MENU(submenu_recent_files), menu_item);
1092 SIGNAL_CONNECT_OBJECT(GTK_OBJECT(menu_item), "activate",
1093 menu_open_recent_file_cmd_cb, (GtkObject *) menu_item);
1094 gtk_widget_show (menu_item);
1096 /* add seperator at last position */
1097 menu_item = gtk_menu_item_new();
1098 gtk_menu_append (GTK_MENU(submenu_recent_files), menu_item);
1099 gtk_widget_show (menu_item);
1101 /* add new "clear list" item at last position */
1102 #if GTK_MAJOR_VERSION < 2
1103 menu_item = gtk_menu_item_new_with_label("<Clear File List>");
1105 menu_item = gtk_image_menu_item_new_from_stock(GTK_STOCK_CLEAR, NULL);
1107 gtk_menu_append (GTK_MENU(submenu_recent_files), menu_item);
1108 SIGNAL_CONNECT_OBJECT(GTK_OBJECT(menu_item), "activate",
1109 clear_menu_recent_capture_file_cmd_cb, (GtkObject *) menu_item);
1110 gtk_widget_show (menu_item);
1112 update_menu_recent_capture_file(submenu_recent_files);
1116 /* add the capture filename to the "Recent Files" menu */
1117 /* (will change nothing, if this filename is already in the menu) */
1119 add_menu_recent_capture_file(gchar *cf_name) {
1124 /* if this filename is an absolute path, we can use it directly */
1125 if (g_path_is_absolute(cf_name)) {
1126 add_menu_recent_capture_file_absolute(cf_name);
1130 /* this filename is not an absolute path, prepend the current dir */
1131 curr = g_get_current_dir();
1132 absolute = g_strdup_printf("%s%s%s", curr, G_DIR_SEPARATOR_S, cf_name);
1133 add_menu_recent_capture_file_absolute(absolute);
1139 /* write all capture filenames of the menu to the user's recent file */
1141 menu_recent_file_write_all(FILE *rf) {
1142 GtkWidget *submenu_recent_files;
1148 submenu_recent_files = gtk_item_factory_get_widget(main_menu_factory, MENU_RECENT_FILES_PATH);
1150 /* we have to iterate backwards through the children's list,
1151 * so we get the latest item last in the file.
1152 * (don't use gtk_container_foreach() here, it will return the wrong iteration order) */
1153 children = gtk_container_children(GTK_CONTAINER(submenu_recent_files));
1154 child = g_list_last(children);
1155 while(child != NULL) {
1156 /* get capture filename from the menu item label */
1157 cf_name = OBJECT_GET_DATA(child->data, MENU_RECENT_FILES_KEY);
1159 fprintf (rf, RECENT_KEY_CAPTURE_FILE ": %s\n", cf_name);
1162 child = g_list_previous(child);
1165 g_list_free(children);
1170 main_toolbar_show_cb(GtkWidget *w _U_, gpointer d _U_)
1173 /* save current setting in recent */
1174 recent.main_toolbar_show = GTK_CHECK_MENU_ITEM(w)->active;
1176 main_widgets_show_or_hide();
1181 filter_toolbar_show_cb(GtkWidget *w _U_, gpointer d _U_)
1184 /* save current setting in recent */
1185 recent.filter_toolbar_show = GTK_CHECK_MENU_ITEM(w)->active;
1187 main_widgets_show_or_hide();
1192 packet_list_show_cb(GtkWidget *w _U_, gpointer d _U_)
1195 /* save current setting in recent */
1196 recent.packet_list_show = GTK_CHECK_MENU_ITEM(w)->active;
1198 main_widgets_show_or_hide();
1203 tree_view_show_cb(GtkWidget *w _U_, gpointer d _U_)
1206 /* save current setting in recent */
1207 recent.tree_view_show = GTK_CHECK_MENU_ITEM(w)->active;
1209 main_widgets_show_or_hide();
1214 byte_view_show_cb(GtkWidget *w _U_, gpointer d _U_)
1217 /* save current setting in recent */
1218 recent.byte_view_show = GTK_CHECK_MENU_ITEM(w)->active;
1220 main_widgets_show_or_hide();
1225 statusbar_show_cb(GtkWidget *w _U_, gpointer d _U_)
1228 /* save current setting in recent */
1229 recent.statusbar_show = GTK_CHECK_MENU_ITEM(w)->active;
1231 main_widgets_show_or_hide();
1236 timestamp_absolute_cb(GtkWidget *w _U_, gpointer d _U_)
1238 if (recent.gui_time_format != TS_ABSOLUTE) {
1239 set_timestamp_setting(TS_ABSOLUTE);
1240 recent.gui_time_format = TS_ABSOLUTE;
1241 change_time_formats(&cfile);
1246 timestamp_absolute_date_cb(GtkWidget *w _U_, gpointer d _U_)
1248 if (recent.gui_time_format != TS_ABSOLUTE_WITH_DATE) {
1249 set_timestamp_setting(TS_ABSOLUTE_WITH_DATE);
1250 recent.gui_time_format = TS_ABSOLUTE_WITH_DATE;
1251 change_time_formats(&cfile);
1256 timestamp_relative_cb(GtkWidget *w _U_, gpointer d _U_)
1258 if (recent.gui_time_format != TS_RELATIVE) {
1259 set_timestamp_setting(TS_RELATIVE);
1260 recent.gui_time_format = TS_RELATIVE;
1261 change_time_formats(&cfile);
1266 timestamp_delta_cb(GtkWidget *w _U_, gpointer d _U_)
1268 if (recent.gui_time_format != TS_DELTA) {
1269 set_timestamp_setting(TS_DELTA);
1270 recent.gui_time_format = TS_DELTA;
1271 change_time_formats(&cfile);
1276 menu_name_resolution_changed(void)
1278 GtkWidget *menu = NULL;
1280 menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Name Resolution/Enable for MAC Layer");
1281 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), g_resolv_flags & RESOLV_MAC);
1283 menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Name Resolution/Enable for Network Layer");
1284 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), g_resolv_flags & RESOLV_NETWORK);
1286 menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Name Resolution/Enable for Transport Layer");
1287 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), g_resolv_flags & RESOLV_TRANSPORT);
1291 name_resolution_mac_cb(GtkWidget *w _U_, gpointer d _U_)
1293 if (GTK_CHECK_MENU_ITEM(w)->active) {
1294 g_resolv_flags |= RESOLV_MAC;
1296 g_resolv_flags &= ~RESOLV_MAC;
1301 name_resolution_network_cb(GtkWidget *w _U_, gpointer d _U_)
1303 if (GTK_CHECK_MENU_ITEM(w)->active) {
1304 g_resolv_flags |= RESOLV_NETWORK;
1306 g_resolv_flags &= ~RESOLV_NETWORK;
1311 name_resolution_transport_cb(GtkWidget *w _U_, gpointer d _U_)
1313 if (GTK_CHECK_MENU_ITEM(w)->active) {
1314 g_resolv_flags |= RESOLV_TRANSPORT;
1316 g_resolv_flags &= ~RESOLV_TRANSPORT;
1322 auto_scroll_live_cb(GtkWidget *w _U_, gpointer d _U_)
1324 auto_scroll_live = GTK_CHECK_MENU_ITEM(w)->active;
1328 /* the recent file read has finished, update the menu corresponding */
1330 menu_recent_read_finished(void) {
1331 GtkWidget *menu = NULL;
1333 menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Main Toolbar");
1334 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), recent.main_toolbar_show);
1336 menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Filter Toolbar");
1337 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), recent.filter_toolbar_show);
1339 menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Statusbar");
1340 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), recent.statusbar_show);
1342 menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Packet List");
1343 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), recent.packet_list_show);
1345 menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Packet Details");
1346 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), recent.tree_view_show);
1348 menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Packet Bytes");
1349 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), recent.byte_view_show);
1351 menu_name_resolution_changed();
1354 menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Auto Scroll in Live Capture");
1355 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), auto_scroll_live);
1358 main_widgets_rearrange();
1360 /* don't change the time format, if we had a command line value */
1361 if (get_timestamp_setting() != TS_NOT_SET) {
1362 recent.gui_time_format = get_timestamp_setting();
1365 switch(recent.gui_time_format) {
1367 menu = gtk_item_factory_get_widget(main_menu_factory,
1368 "/View/Time Display Format/Time of Day");
1369 /* set_active will not trigger the callback when activating an active item! */
1370 recent.gui_time_format = -1;
1371 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), FALSE);
1372 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), TRUE);
1374 case(TS_ABSOLUTE_WITH_DATE):
1375 menu = gtk_item_factory_get_widget(main_menu_factory,
1376 "/View/Time Display Format/Date and Time of Day");
1377 recent.gui_time_format = -1;
1378 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), TRUE);
1381 menu = gtk_item_factory_get_widget(main_menu_factory,
1382 "/View/Time Display Format/Seconds Since Beginning of Capture");
1383 recent.gui_time_format = -1;
1384 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), TRUE);
1387 menu = gtk_item_factory_get_widget(main_menu_factory,
1388 "/View/Time Display Format/Seconds Since Previous Packet");
1389 recent.gui_time_format = -1;
1390 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), TRUE);
1393 g_assert_not_reached();
1399 popup_menu_handler(GtkWidget *widget, GdkEvent *event, gpointer data)
1401 GtkWidget *menu = (GtkWidget *)data;
1402 GdkEventButton *event_button = NULL;
1405 if(widget == NULL || event == NULL || data == NULL) {
1410 * If we ever want to make the menu differ based on what row
1411 * and/or column we're above, we'd use "eth_clist_get_selection_info()"
1412 * to find the row and column number for the coordinates; a CTree is,
1413 * I guess, like a CList with one column(?) and the expander widget
1416 /* Check if we are on packet_list object */
1417 if (widget == OBJECT_GET_DATA(popup_menu_object, E_MPACKET_LIST_KEY)) {
1418 if (packet_list_get_event_row_column(widget, (GdkEventButton *)event,
1420 OBJECT_SET_DATA(popup_menu_object, E_MPACKET_LIST_ROW_KEY,
1421 GINT_TO_POINTER(row));
1422 OBJECT_SET_DATA(popup_menu_object, E_MPACKET_LIST_COL_KEY,
1423 GINT_TO_POINTER(column));
1424 packet_list_set_selected_row(row);
1428 /* Check if we are on tree_view object */
1429 if (widget == tree_view) {
1430 tree_view_select(widget, (GdkEventButton *) event);
1433 /* Check if we are on byte_view object */
1434 if(widget == get_notebook_bv_ptr(byte_nb_ptr)) {
1435 byte_view_select(widget, (GdkEventButton *) event);
1438 /* context menu handler (but the byte view notebook pages have their own handler) */
1439 if(event->type == GDK_BUTTON_PRESS && widget != byte_nb_ptr) {
1440 event_button = (GdkEventButton *) event;
1442 /* To qoute the "Gdk Event Structures" doc:
1443 * "Normally button 1 is the left mouse button, 2 is the middle button, and 3 is the right button" */
1444 if(event_button->button == 3) {
1445 gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL,
1446 event_button->button,
1447 event_button->time);
1448 SIGNAL_EMIT_STOP_BY_NAME(widget, "button_press_event");
1452 #if GTK_MAJOR_VERSION >= 2
1453 /* GDK_2BUTTON_PRESS is a doubleclick -> expand/collapse tree row */
1454 /* GTK version 1 seems to be doing this automatically */
1455 if (widget == tree_view && event->type == GDK_2BUTTON_PRESS) {
1458 if (gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(widget),
1459 (gint) (((GdkEventButton *)event)->x),
1460 (gint) (((GdkEventButton *)event)->y),
1461 &path, NULL, NULL, NULL))
1463 if (gtk_tree_view_row_expanded(GTK_TREE_VIEW(widget), path))
1464 gtk_tree_view_collapse_row(GTK_TREE_VIEW(widget), path);
1466 gtk_tree_view_expand_row(GTK_TREE_VIEW(widget), path,
1468 gtk_tree_path_free(path);
1475 /* Enable or disable menu items based on whether you have a capture file
1476 you've finished reading. */
1478 set_menus_for_capture_file(gboolean have_capture_file)
1480 set_menu_sensitivity(main_menu_factory, "/File/Open...", have_capture_file);
1481 set_menu_sensitivity(main_menu_factory, "/File/Open Recent", have_capture_file);
1482 set_menu_sensitivity(main_menu_factory, "/File/Merge...", have_capture_file);
1483 set_menu_sensitivity(main_menu_factory, "/File/Close", have_capture_file);
1484 set_menu_sensitivity(main_menu_factory, "/File/Save As...",
1486 set_menu_sensitivity(main_menu_factory, "/File/Export", have_capture_file);
1487 set_menu_sensitivity(main_menu_factory, "/View/Reload", have_capture_file);
1488 set_toolbar_for_capture_file(have_capture_file);
1489 packets_bar_update();
1492 /* Enable or disable menu items based on whether you have an unsaved
1493 capture file you've finished reading. */
1495 set_menus_for_unsaved_capture_file(gboolean have_unsaved_capture_file)
1497 set_menu_sensitivity(main_menu_factory, "/File/Save",
1498 have_unsaved_capture_file);
1499 set_toolbar_for_unsaved_capture_file(have_unsaved_capture_file);
1502 /* Enable or disable menu items based on whether there's a capture in
1505 set_menus_for_capture_in_progress(gboolean capture_in_progress)
1507 set_menu_sensitivity(main_menu_factory, "/File/Open...",
1508 !capture_in_progress);
1509 set_menu_sensitivity(main_menu_factory, "/File/Open Recent",
1510 !capture_in_progress);
1512 set_menu_sensitivity(main_menu_factory, "/Capture/Start...",
1513 !capture_in_progress);
1514 set_menu_sensitivity(main_menu_factory, "/Capture/Stop",
1515 capture_in_progress);
1516 #endif /* HAVE_LIBPCAP */
1517 set_toolbar_for_capture_in_progress(capture_in_progress);
1519 set_capture_if_dialog_for_capture_in_progress(capture_in_progress);
1522 /* Enable or disable menu items based on whether you have some captured
1525 walk_menu_tree_for_captured_packets(GList *node,
1526 gboolean have_captured_packets)
1528 gboolean is_enabled;
1530 menu_item_t *node_data = node->data;
1533 * Is this a leaf node or an interior node?
1535 if (node_data->children == NULL) {
1539 * If it has no "selected_packet_enabled()" or
1540 * "selected_tree_row_enabled()" routines, we enable
1541 * it. This allows tap windows to be popped up even
1542 * if you have no capture file; this is done to let
1543 * the user pop up multiple tap windows before reading
1544 * in a capture file, so that they can be processed in
1545 * parallel while the capture file is being read rather
1546 * than one at at time as you pop up the windows, and to
1547 * let the user pop up tap windows before starting an
1548 * "Update list of packets in real time" capture, so that
1549 * the statistics can be displayed while the capture is
1552 * If it has either of those routines, we disable it for
1553 * now - as long as, when a capture is first available,
1554 * we don't get called after a packet or tree row is
1555 * selected, that's OK.
1556 * XXX - that should be done better.
1558 if (node_data->selected_packet_enabled == NULL &&
1559 node_data->selected_tree_row_enabled == NULL)
1560 node_data->enabled = TRUE;
1562 node_data->enabled = FALSE;
1565 * It's an interior node; call
1566 * "walk_menu_tree_for_captured_packets()" on all its
1567 * children and, if any of them are enabled, enable
1568 * this node, otherwise disable it.
1570 * XXX - should we just leave all interior nodes enabled?
1571 * Which is a better UI choice?
1574 for (child = node_data->children; child != NULL; child =
1576 if (walk_menu_tree_for_captured_packets(child,
1577 have_captured_packets))
1580 node_data->enabled = is_enabled;
1584 * The root node doesn't correspond to a menu tree item; it
1585 * has a null name pointer.
1587 if (node_data->name != NULL) {
1588 set_menu_sensitivity(main_menu_factory, node_data->name,
1589 node_data->enabled);
1591 return node_data->enabled;
1595 set_menus_for_captured_packets(gboolean have_captured_packets)
1597 set_menu_sensitivity(main_menu_factory, "/File/Print...",
1598 have_captured_packets);
1599 set_menu_sensitivity(packet_list_menu_factory, "/Print...",
1600 have_captured_packets);
1601 set_menu_sensitivity(main_menu_factory, "/Edit/Find Packet...",
1602 have_captured_packets);
1603 set_menu_sensitivity(main_menu_factory, "/Edit/Find Next",
1604 have_captured_packets);
1605 set_menu_sensitivity(main_menu_factory, "/Edit/Find Previous",
1606 have_captured_packets);
1607 set_menu_sensitivity(main_menu_factory, "/View/Zoom In",
1608 have_captured_packets);
1609 set_menu_sensitivity(main_menu_factory, "/View/Zoom Out",
1610 have_captured_packets);
1611 set_menu_sensitivity(main_menu_factory, "/View/Normal Size",
1612 have_captured_packets);
1613 set_menu_sensitivity(packet_list_menu_factory, "/Coloring Rules...",
1614 have_captured_packets);
1615 set_menu_sensitivity(main_menu_factory, "/Go/Go to Packet...",
1616 have_captured_packets);
1617 set_menu_sensitivity(main_menu_factory, "/Go/First Packet",
1618 have_captured_packets);
1619 set_menu_sensitivity(main_menu_factory, "/Go/Last Packet",
1620 have_captured_packets);
1621 set_menu_sensitivity(main_menu_factory, "/Statistics/Summary",
1622 have_captured_packets);
1623 set_menu_sensitivity(main_menu_factory, "/Statistics/Protocol Hierarchy",
1624 have_captured_packets);
1626 walk_menu_tree_for_captured_packets(tap_menu_tree_root,
1627 have_captured_packets);
1628 set_toolbar_for_captured_packets(have_captured_packets);
1629 packets_bar_update();
1632 /* Enable or disable menu items based on whether a packet is selected and,
1633 if so, on the properties of the packet. */
1635 walk_menu_tree_for_selected_packet(GList *node, frame_data *fd,
1636 epan_dissect_t *edt)
1638 gboolean is_enabled;
1640 menu_item_t *node_data = node->data;
1643 * Is this a leaf node or an interior node?
1645 if (node_data->children == NULL) {
1649 * If it has no "selected_packet_enabled()" routine,
1650 * leave its enabled/disabled status alone - it
1651 * doesn't depend on whether we have a packet selected
1652 * or not or on the selected packet.
1654 * If it has a "selected_packet_enabled()" routine,
1655 * call it and set the item's enabled/disabled status
1656 * based on its return value.
1658 if (node_data->selected_packet_enabled != NULL)
1659 node_data->enabled = node_data->selected_packet_enabled(fd, edt);
1662 * It's an interior node; call
1663 * "walk_menu_tree_for_selected_packet()" on all its
1664 * children and, if any of them are enabled, enable
1665 * this node, otherwise disable it.
1667 * XXX - should we just leave all interior nodes enabled?
1668 * Which is a better UI choice?
1671 for (child = node_data->children; child != NULL; child =
1673 if (walk_menu_tree_for_selected_packet(child, fd, edt))
1676 node_data->enabled = is_enabled;
1680 * The root node doesn't correspond to a menu tree item; it
1681 * has a null name pointer.
1683 if (node_data->name != NULL) {
1684 set_menu_sensitivity(main_menu_factory, node_data->name,
1685 node_data->enabled);
1687 return node_data->enabled;
1691 set_menus_for_selected_packet(capture_file *cf)
1693 set_menu_sensitivity(main_menu_factory, "/Edit/Mark Packet",
1694 cf->current_frame != NULL);
1695 set_menu_sensitivity(packet_list_menu_factory, "/Mark Packet",
1696 cf->current_frame != NULL);
1697 set_menu_sensitivity(main_menu_factory, "/Edit/Time Reference",
1698 cf->current_frame != NULL);
1699 set_menu_sensitivity(packet_list_menu_factory, "/Time Reference",
1700 cf->current_frame != NULL);
1701 set_menu_sensitivity(main_menu_factory, "/Edit/Mark All Packets",
1702 cf->current_frame != NULL);
1703 set_menu_sensitivity(main_menu_factory, "/Edit/Unmark All Packets",
1704 cf->current_frame != NULL);
1705 set_menu_sensitivity(main_menu_factory, "/View/Collapse All",
1706 cf->current_frame != NULL);
1707 set_menu_sensitivity(tree_view_menu_factory, "/Collapse All",
1708 cf->current_frame != NULL);
1709 set_menu_sensitivity(main_menu_factory, "/View/Expand All",
1710 cf->current_frame != NULL);
1711 set_menu_sensitivity(tree_view_menu_factory, "/Expand All",
1712 cf->current_frame != NULL);
1713 set_menu_sensitivity(main_menu_factory, "/View/Show Packet in New Window",
1714 cf->current_frame != NULL);
1715 set_menu_sensitivity(packet_list_menu_factory, "/Show Packet in New Window",
1716 cf->current_frame != NULL);
1717 set_menu_sensitivity(main_menu_factory, "/Analyze/Follow TCP Stream",
1718 cf->current_frame != NULL ? (cf->edt->pi.ipproto == IP_PROTO_TCP) : FALSE);
1719 set_menu_sensitivity(NULL, "/Follow TCP Stream",
1720 cf->current_frame != NULL ? (cf->edt->pi.ipproto == IP_PROTO_TCP) : FALSE);
1721 set_menu_sensitivity(main_menu_factory, "/Analyze/Decode As...",
1722 cf->current_frame != NULL && decode_as_ok());
1723 set_menu_sensitivity(NULL, "/Decode As...",
1724 cf->current_frame != NULL && decode_as_ok());
1725 set_menu_sensitivity(main_menu_factory, "/View/Name Resolution/Resolve Name",
1726 cf->current_frame != NULL && (g_resolv_flags & RESOLV_ALL_ADDRS) != RESOLV_ALL_ADDRS);
1727 set_menu_sensitivity(tree_view_menu_factory, "/Resolve Name",
1728 cf->current_frame != NULL && (g_resolv_flags & RESOLV_ALL_ADDRS) != RESOLV_ALL_ADDRS);
1729 set_menu_sensitivity(packet_list_menu_factory, "/Apply as Filter",
1730 cf->current_frame != NULL);
1731 set_menu_sensitivity(packet_list_menu_factory, "/Prepare a Filter",
1732 cf->current_frame != NULL);
1734 walk_menu_tree_for_selected_packet(tap_menu_tree_root, cf->current_frame,
1736 packets_bar_update();
1739 /* Enable or disable menu items based on whether a tree row is selected
1740 and, if so, on the properties of the tree row. */
1742 walk_menu_tree_for_selected_tree_row(GList *node, field_info *fi)
1744 gboolean is_enabled;
1746 menu_item_t *node_data = node->data;
1749 * Is this a leaf node or an interior node?
1751 if (node_data->children == NULL) {
1755 * If it has no "selected_tree_row_enabled()" routine,
1756 * leave its enabled/disabled status alone - it
1757 * doesn't depend on whether we have a tree row selected
1758 * or not or on the selected tree row.
1760 * If it has a "selected_tree_row_enabled()" routine,
1761 * call it and set the item's enabled/disabled status
1762 * based on its return value.
1764 if (node_data->selected_tree_row_enabled != NULL)
1765 node_data->enabled = node_data->selected_tree_row_enabled(fi);
1768 * It's an interior node; call
1769 * "walk_menu_tree_for_selected_tree_row()" on all its
1770 * children and, if any of them are enabled, enable
1771 * this node, otherwise disable it.
1773 * XXX - should we just leave all interior nodes enabled?
1774 * Which is a better UI choice?
1777 for (child = node_data->children; child != NULL; child =
1779 if (walk_menu_tree_for_selected_tree_row(child, fi))
1782 node_data->enabled = is_enabled;
1786 * The root node doesn't correspond to a menu tree item; it
1787 * has a null name pointer.
1789 if (node_data->name != NULL) {
1790 set_menu_sensitivity(main_menu_factory, node_data->name,
1791 node_data->enabled);
1793 return node_data->enabled;
1797 set_menus_for_selected_tree_row(capture_file *cf)
1799 gboolean properties;
1802 set_menu_sensitivity(main_menu_factory, "/File/Export/Selected Packet Bytes...",
1803 cf->finfo_selected != NULL);
1804 set_menu_sensitivity(tree_view_menu_factory, "/Export Selected Packet Bytes...",
1805 cf->finfo_selected != NULL);
1806 set_menu_sensitivity(hexdump_menu_factory, "/Export Selected Packet Bytes...",
1807 cf->finfo_selected != NULL);
1809 if (cf->finfo_selected != NULL) {
1810 header_field_info *hfinfo = cf->finfo_selected->hfinfo;
1811 if (hfinfo->parent == -1) {
1812 properties = prefs_is_registered_protocol(hfinfo->abbrev);
1814 properties = prefs_is_registered_protocol(proto_registrar_get_abbrev(hfinfo->parent));
1816 set_menu_sensitivity(main_menu_factory,
1817 "/Go/Go to Corresponding Packet", hfinfo->type == FT_FRAMENUM);
1818 set_menu_sensitivity(tree_view_menu_factory,
1819 "/Go to Corresponding Packet", hfinfo->type == FT_FRAMENUM);
1820 set_menu_sensitivity(main_menu_factory, "/Analyze/Apply as Filter",
1821 proto_can_match_selected(cf->finfo_selected, cf->edt));
1822 set_menu_sensitivity(tree_view_menu_factory, "/Apply as Filter",
1823 proto_can_match_selected(cf->finfo_selected, cf->edt));
1824 set_menu_sensitivity(main_menu_factory, "/Analyze/Prepare a Filter",
1825 proto_can_match_selected(cf->finfo_selected, cf->edt));
1826 set_menu_sensitivity(tree_view_menu_factory, "/Prepare a Filter",
1827 proto_can_match_selected(cf->finfo_selected, cf->edt));
1828 set_menu_sensitivity(tree_view_menu_factory, "/Protocol Preferences...",
1830 set_menu_sensitivity(main_menu_factory, "/View/Expand Tree", cf->finfo_selected->tree_type != -1);
1831 set_menu_sensitivity(tree_view_menu_factory, "/Expand Tree", cf->finfo_selected->tree_type != -1);
1833 set_menu_sensitivity(main_menu_factory,
1834 "/Go/Go to Corresponding Packet", FALSE);
1835 set_menu_sensitivity(tree_view_menu_factory,
1836 "/Go to Corresponding Packet", FALSE);
1837 set_menu_sensitivity(main_menu_factory, "/Analyze/Apply as Filter", FALSE);
1838 set_menu_sensitivity(tree_view_menu_factory, "/Apply as Filter", FALSE);
1839 set_menu_sensitivity(main_menu_factory, "/Analyze/Prepare a Filter", FALSE);
1840 set_menu_sensitivity(tree_view_menu_factory, "/Prepare a Filter", FALSE);
1841 set_menu_sensitivity(tree_view_menu_factory, "/Protocol Preferences...",
1843 set_menu_sensitivity(main_menu_factory, "/View/Expand Tree", FALSE);
1844 set_menu_sensitivity(tree_view_menu_factory, "/Expand Tree", FALSE);
1847 walk_menu_tree_for_selected_tree_row(tap_menu_tree_root, cf->finfo_selected);