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>
38 #include <epan/prefs.h>
40 #include <epan/timestamp.h>
41 #include <epan/ipproto.h>
43 #include "about_dlg.h"
44 #include "capture_dlg.h"
45 #include "color_dlg.h"
46 #include "filter_dlg.h"
47 #include "dlg_utils.h"
51 #include "summary_dlg.h"
52 #include "prefs_dlg.h"
53 #include "packet_win.h"
55 #include "follow_dlg.h"
56 #include "decode_as_dlg.h"
58 #include "supported_protos_dlg.h"
59 #include "proto_dlg.h"
60 #include "proto_hier_stats_dlg.h"
62 #include <epan/plugins.h>
63 #include <epan/epan_dissect.h>
64 #include "compat_macros.h"
66 #include "gtkglobals.h"
69 #include "packet_list.h"
72 #include "../ui_util.h"
73 #include "proto_draw.h"
74 #include "conversations_table.h"
75 #include "hostlist_table.h"
76 #include "simple_dialog.h"
77 #include "packet_history.h"
78 #include "color_filters.h"
80 GtkWidget *popup_menu_object;
83 clear_menu_recent_capture_file_cmd_cb(GtkWidget *w, gpointer unused _U_);
85 typedef struct _menu_item {
89 GtkItemFactoryCallback callback;
90 gpointer callback_data;
91 gboolean (*selected_packet_enabled)(frame_data *, epan_dissect_t *);
92 gboolean (*selected_tree_row_enabled)(field_info *);
96 static GList *tap_menu_tree_root = NULL;
99 merge_all_tap_menus(GList *node);
101 #define GTK_MENU_FUNC(a) ((GtkItemFactoryCallback)(a))
103 static void menus_init(void);
104 static void set_menu_sensitivity (GtkItemFactory *, const gchar *, gint);
105 static void main_toolbar_show_cb(GtkWidget *w _U_, gpointer d _U_);
106 static void filter_toolbar_show_cb(GtkWidget *w _U_, gpointer d _U_);
107 static void packet_list_show_cb(GtkWidget *w _U_, gpointer d _U_);
108 static void tree_view_show_cb(GtkWidget *w _U_, gpointer d _U_);
109 static void byte_view_show_cb(GtkWidget *w _U_, gpointer d _U_);
110 static void statusbar_show_cb(GtkWidget *w _U_, gpointer d _U_);
111 static void timestamp_absolute_cb(GtkWidget *w _U_, gpointer d _U_);
112 static void timestamp_absolute_date_cb(GtkWidget *w _U_, gpointer d _U_);
113 static void timestamp_relative_cb(GtkWidget *w _U_, gpointer d _U_);
114 static void timestamp_delta_cb(GtkWidget *w _U_, gpointer d _U_);
115 static void name_resolution_mac_cb(GtkWidget *w _U_, gpointer d _U_);
116 static void name_resolution_network_cb(GtkWidget *w _U_, gpointer d _U_);
117 static void name_resolution_transport_cb(GtkWidget *w _U_, gpointer d _U_);
119 static void auto_scroll_live_cb(GtkWidget *w _U_, gpointer d _U_);
121 static void colorize_cb(GtkWidget *w _U_, gpointer d _U_);
123 /* This is the GtkItemFactoryEntry structure used to generate new menus.
124 Item 1: The menu path. The letter after the underscore indicates an
125 accelerator key once the menu is open.
126 Item 2: The accelerator key for the entry
127 Item 3: The callback function.
128 Item 4: The callback action. This changes the parameters with
129 which the function is called. The default is 0.
130 Item 5: The item type, used to define what kind of an item it is.
131 Here are the possible values:
135 "<Title>" -> create a title item
136 "<Item>" -> create a simple item
137 "<ImageItem>" -> create an item holding an image (gtk2)
138 "<StockItem>" -> create an item holding a stock image (gtk2)
139 "<CheckItem>" -> create a check item
140 "<ToggleItem>" -> create a toggle item
141 "<RadioItem>" -> create a radio item
142 <path> -> path of a radio item to link against
143 "<Separator>" -> create a separator
144 "<Tearoff>" -> create a tearoff separator (gtk2)
145 "<Branch>" -> create an item to hold sub items (optional)
146 "<LastBranch>" -> create a right justified branch
147 Item 6: extra data needed for ImageItem and StockItem (gtk2)
150 /* As a general GUI guideline, we try to follow the Gnome Human Interface Guidelines, which can be found at:
151 http://developer.gnome.org/projects/gup/hig/1.0/index.html
153 Please note: there are some differences between the Gnome HIG menu suggestions and our implementation:
155 File/Open Recent: the Gnome HIG suggests putting the list of recently used files as elements into the File menuitem.
156 As this is ok for only a few items, this will become unhandy for 10 or even more list entries.
157 For this reason, we use a submenu for this.
159 File/Close: the Gnome HIG suggests putting this item just above the Quit item.
160 This results in unintuitive behaviour as both Close and Quit items are very near together.
161 By putting the Close item near the open item(s), it better suggests that it will close the
162 currently opened/captured file only.
167 static GtkItemFactoryEntry menu_items[] =
169 ITEM_FACTORY_ENTRY("/_File", NULL, NULL, 0, "<Branch>", NULL),
170 ITEM_FACTORY_STOCK_ENTRY("/File/_Open...", "<control>O", file_open_cmd_cb,
172 ITEM_FACTORY_ENTRY("/File/Open _Recent", NULL, NULL, 0, "<Branch>", NULL),
173 ITEM_FACTORY_ENTRY("/File/_Merge...", NULL, file_merge_cmd_cb, 0, NULL, NULL),
174 ITEM_FACTORY_STOCK_ENTRY("/File/_Close", "<control>W", file_close_cmd_cb,
176 ITEM_FACTORY_ENTRY("/File/<separator>", NULL, NULL, 0, "<Separator>", NULL),
177 ITEM_FACTORY_STOCK_ENTRY("/File/_Save", "<control>S", file_save_cmd_cb,
179 ITEM_FACTORY_STOCK_ENTRY("/File/Save _As...", "<shift><control>S", file_save_as_cmd_cb,
180 0, GTK_STOCK_SAVE_AS),
181 ITEM_FACTORY_ENTRY("/File/<separator>", NULL, NULL, 0, "<Separator>", NULL),
182 ITEM_FACTORY_ENTRY("/File/_Export", NULL, NULL, 0, "<Branch>", NULL),
183 ITEM_FACTORY_ENTRY("/File/Export/as \"Plain _Text\" file...", NULL, export_text_cmd_cb,
185 ITEM_FACTORY_ENTRY("/File/Export/as \"_PostScript\" file...", NULL, export_ps_cmd_cb,
187 ITEM_FACTORY_ENTRY("/File/Export/as \"_CSV\" (Comma Separated Values packet summary) file...",
188 NULL, export_csv_cmd_cb, 0, NULL, NULL),
189 ITEM_FACTORY_ENTRY("/File/Export/<separator>", NULL, NULL, 0, "<Separator>", NULL),
190 ITEM_FACTORY_ENTRY("/File/Export/as XML - \"P_SML\" (packet summary) file...", NULL, export_psml_cmd_cb,
192 ITEM_FACTORY_ENTRY("/File/Export/as XML - \"P_DML\" (packet details) file...", NULL, export_pdml_cmd_cb,
194 ITEM_FACTORY_ENTRY("/File/Export/<separator>", NULL, NULL, 0, "<Separator>", NULL),
195 ITEM_FACTORY_ENTRY("/File/Export/Selected Packet _Bytes...", "<control>H", savehex_cb,
197 ITEM_FACTORY_ENTRY("/File/<separator>", NULL, NULL, 0, "<Separator>", NULL),
198 ITEM_FACTORY_STOCK_ENTRY("/File/_Print...", "<control>P", file_print_cmd_cb,
200 ITEM_FACTORY_ENTRY("/File/<separator>", NULL, NULL, 0, "<Separator>", NULL),
201 ITEM_FACTORY_STOCK_ENTRY("/File/_Quit", "<control>Q", file_quit_cmd_cb,
203 ITEM_FACTORY_ENTRY("/_Edit", NULL, NULL, 0, "<Branch>", NULL),
205 /* Un-#if this when we actually implement Cut/Copy/Paste. */
206 ITEM_FACTORY_STOCK_ENTRY("/Edit/Cut", "<control>X", NULL,
208 ITEM_FACTORY_STOCK_ENTRY("/Edit/Copy", "<control>C", NULL,
210 ITEM_FACTORY_STOCK_ENTRY("/Edit/Paste", "<control>V", NULL,
212 ITEM_FACTORY_ENTRY("/Edit/<separator>", NULL, NULL, 0, "<Separator>"),
214 ITEM_FACTORY_STOCK_ENTRY("/Edit/_Find Packet...", "<control>F",
215 find_frame_cb, 0, GTK_STOCK_FIND),
216 ITEM_FACTORY_ENTRY("/Edit/Find Ne_xt", "<control>N", find_next_cb, 0, NULL, NULL),
217 ITEM_FACTORY_ENTRY("/Edit/Find Pre_vious", "<control>B", find_previous_cb, 0, NULL, NULL),
218 ITEM_FACTORY_ENTRY("/Edit/<separator>", NULL, NULL, 0, "<Separator>", NULL),
219 ITEM_FACTORY_ENTRY("/Edit/_Time Reference", NULL, NULL, 0, "<Branch>", NULL),
220 ITEM_FACTORY_STOCK_ENTRY("/Edit/Time Reference/Set Time Reference (toggle)", "<control>T", reftime_frame_cb,
221 REFTIME_TOGGLE, ETHEREAL_STOCK_TIME),
222 ITEM_FACTORY_ENTRY("/Edit/Time Reference/Find Next", NULL, reftime_frame_cb, REFTIME_FIND_NEXT, NULL, NULL),
223 ITEM_FACTORY_ENTRY("/Edit/Time Reference/Find Previous", NULL, reftime_frame_cb, REFTIME_FIND_PREV, NULL, NULL),
224 ITEM_FACTORY_ENTRY("/Edit/_Mark Packet (toggle)", "<control>M", mark_frame_cb,
226 ITEM_FACTORY_ENTRY("/Edit/Mark _All Packets", NULL, mark_all_frames_cb,
228 ITEM_FACTORY_ENTRY("/Edit/_Unmark All Packets", NULL, unmark_all_frames_cb,
230 ITEM_FACTORY_ENTRY("/Edit/<separator>", NULL, NULL, 0, "<Separator>", NULL),
231 ITEM_FACTORY_STOCK_ENTRY("/Edit/_Preferences...", "<shift><control>P", prefs_cb,
232 0, GTK_STOCK_PREFERENCES),
233 ITEM_FACTORY_ENTRY("/_View", NULL, NULL, 0, "<Branch>", NULL),
234 ITEM_FACTORY_ENTRY("/View/_Main Toolbar", NULL, main_toolbar_show_cb, 0, "<CheckItem>", NULL),
235 ITEM_FACTORY_ENTRY("/View/_Filter Toolbar", NULL, filter_toolbar_show_cb, 0, "<CheckItem>", NULL),
236 ITEM_FACTORY_ENTRY("/View/_Statusbar", NULL, statusbar_show_cb, 0, "<CheckItem>", NULL),
237 ITEM_FACTORY_ENTRY("/View/<separator>", NULL, NULL, 0, "<Separator>", NULL),
238 ITEM_FACTORY_ENTRY("/View/Packet _List", NULL, packet_list_show_cb, 0, "<CheckItem>", NULL),
239 ITEM_FACTORY_ENTRY("/View/Packet _Details", NULL, tree_view_show_cb, 0, "<CheckItem>", NULL),
240 ITEM_FACTORY_ENTRY("/View/Packet _Bytes", NULL, byte_view_show_cb, 0, "<CheckItem>", NULL),
241 ITEM_FACTORY_ENTRY("/View/<separator>", NULL, NULL, 0, "<Separator>", NULL),
242 ITEM_FACTORY_ENTRY("/View/_Time Display Format", NULL, NULL, 0, "<Branch>", NULL),
243 ITEM_FACTORY_ENTRY("/View/Time Display Format/Time of Day", NULL, timestamp_absolute_cb,
244 0, "<RadioItem>", NULL),
245 ITEM_FACTORY_ENTRY("/View/Time Display Format/Date and Time of Day", NULL, timestamp_absolute_date_cb,
246 0, "/View/Time Display Format/Time of Day", NULL),
247 ITEM_FACTORY_ENTRY("/View/Time Display Format/Seconds Since Beginning of Capture", NULL, timestamp_relative_cb,
248 0, "/View/Time Display Format/Time of Day", NULL),
249 ITEM_FACTORY_ENTRY("/View/Time Display Format/Seconds Since Previous Packet", NULL, timestamp_delta_cb,
250 0, "/View/Time Display Format/Time of Day", NULL),
251 ITEM_FACTORY_ENTRY("/View/Name Resol_ution", NULL, NULL, 0, "<Branch>", NULL),
252 ITEM_FACTORY_ENTRY("/View/Name Resolution/_Resolve Name", NULL, resolve_name_cb, 0, NULL, NULL),
253 ITEM_FACTORY_ENTRY("/View/Name Resolution/<separator>", NULL, NULL, 0, "<Separator>", NULL),
254 ITEM_FACTORY_ENTRY("/View/Name Resolution/Enable for _MAC Layer", NULL, name_resolution_mac_cb, 0, "<CheckItem>", NULL),
255 ITEM_FACTORY_ENTRY("/View/Name Resolution/Enable for _Network Layer", NULL, name_resolution_network_cb, 0, "<CheckItem>", NULL),
256 ITEM_FACTORY_ENTRY("/View/Name Resolution/Enable for _Transport Layer", NULL, name_resolution_transport_cb, 0, "<CheckItem>", NULL),
257 ITEM_FACTORY_ENTRY("/View/Colorize Packet List", NULL, colorize_cb, 0, "<CheckItem>", NULL),
259 ITEM_FACTORY_ENTRY("/View/Auto Scroll in Li_ve Capture", NULL, auto_scroll_live_cb, 0, "<CheckItem>", NULL),
261 ITEM_FACTORY_ENTRY("/View/<separator>", NULL, NULL, 0, "<Separator>", NULL),
262 ITEM_FACTORY_STOCK_ENTRY("/View/_Zoom In", "<control>plus", view_zoom_in_cb,
263 0, GTK_STOCK_ZOOM_IN),
264 ITEM_FACTORY_STOCK_ENTRY("/View/Zoom _Out", "<control>minus", view_zoom_out_cb,
265 0, GTK_STOCK_ZOOM_OUT),
266 ITEM_FACTORY_STOCK_ENTRY("/View/_Normal Size", "<control>equal", view_zoom_100_cb,
267 0, GTK_STOCK_ZOOM_100),
268 ITEM_FACTORY_STOCK_ENTRY("/View/Resize All Columns", NULL, packet_list_resize_columns_cb,
269 0, ETHEREAL_STOCK_RESIZE_COLUMNS),
270 ITEM_FACTORY_ENTRY("/View/<separator>", NULL, NULL, 0, "<Separator>", NULL),
271 ITEM_FACTORY_ENTRY("/View/Collapse _All", NULL, collapse_all_cb,
273 ITEM_FACTORY_ENTRY("/View/_Expand All", NULL, expand_all_cb,
275 ITEM_FACTORY_ENTRY("/View/Expand Tree", NULL, expand_tree_cb, 0, NULL, NULL),
276 ITEM_FACTORY_ENTRY("/View/<separator>", NULL, NULL, 0, "<Separator>", NULL),
277 ITEM_FACTORY_STOCK_ENTRY("/View/_Coloring Rules...", NULL, color_display_cb,
278 0, GTK_STOCK_SELECT_COLOR),
279 ITEM_FACTORY_ENTRY("/View/<separator>", NULL, NULL, 0, "<Separator>", NULL),
280 ITEM_FACTORY_ENTRY("/View/Show Packet in New _Window", NULL,
281 new_window_cb, 0, NULL, NULL),
282 ITEM_FACTORY_STOCK_ENTRY("/View/_Reload", "<control>R", file_reload_cmd_cb,
283 0, GTK_STOCK_REFRESH),
284 ITEM_FACTORY_ENTRY("/_Go", NULL, NULL, 0, "<Branch>", NULL),
285 ITEM_FACTORY_STOCK_ENTRY("/Go/_Back", "<alt>Left",
286 history_back_cb, 0, GTK_STOCK_GO_BACK),
287 ITEM_FACTORY_STOCK_ENTRY("/Go/_Forward", "<alt>Right",
288 history_forward_cb, 0, GTK_STOCK_GO_FORWARD),
289 ITEM_FACTORY_STOCK_ENTRY("/Go/_Go to Packet...", "<control>G",
290 goto_frame_cb, 0, GTK_STOCK_JUMP_TO),
291 ITEM_FACTORY_ENTRY("/Go/Go to _Corresponding Packet", NULL, goto_framenum_cb,
293 ITEM_FACTORY_ENTRY("/Go/<separator>", NULL, NULL, 0, "<Separator>", NULL),
294 ITEM_FACTORY_STOCK_ENTRY("/Go/F_irst Packet", NULL,
295 goto_top_frame_cb, 0, GTK_STOCK_GOTO_TOP),
296 ITEM_FACTORY_STOCK_ENTRY("/Go/_Last Packet", NULL,
297 goto_bottom_frame_cb, 0, GTK_STOCK_GOTO_BOTTOM),
299 ITEM_FACTORY_ENTRY("/_Capture", NULL, NULL, 0, "<Branch>", NULL),
300 ITEM_FACTORY_STOCK_ENTRY("/Capture/_Interfaces...", NULL,
301 capture_if_cb, 0, ETHEREAL_STOCK_CAPTURE_INTERFACES),
302 ITEM_FACTORY_STOCK_ENTRY("/Capture/_Options...", "<control>K",
303 capture_prep_cb, 0, ETHEREAL_STOCK_CAPTURE_OPTIONS),
304 ITEM_FACTORY_STOCK_ENTRY("/Capture/_Start", NULL,
305 capture_start_cb, 0, ETHEREAL_STOCK_CAPTURE_START),
306 ITEM_FACTORY_STOCK_ENTRY("/Capture/S_top", "<control>E", capture_stop_cb,
307 0, ETHEREAL_STOCK_CAPTURE_STOP),
308 ITEM_FACTORY_STOCK_ENTRY("/Capture/_Restart", NULL, capture_clear_cb,
309 0, ETHEREAL_STOCK_CAPTURE_RESTART),
310 ITEM_FACTORY_STOCK_ENTRY("/Capture/Capture _Filters...", NULL, cfilter_dialog_cb,
311 0, ETHEREAL_STOCK_CAPTURE_FILTER),
312 #endif /* HAVE_LIBPCAP */
313 ITEM_FACTORY_ENTRY("/_Analyze", NULL, NULL, 0, "<Branch>", NULL),
314 ITEM_FACTORY_STOCK_ENTRY("/Analyze/_Display Filters...", NULL, dfilter_dialog_cb,
315 0, ETHEREAL_STOCK_DISPLAY_FILTER),
316 ITEM_FACTORY_ENTRY("/Analyze/Appl_y as Filter", NULL, NULL, 0, "<Branch>", NULL),
317 ITEM_FACTORY_ENTRY("/Analyze/Apply as Filter/_Selected", NULL, match_selected_ptree_cb,
318 MATCH_SELECTED_REPLACE|MATCH_SELECTED_APPLY_NOW, NULL, NULL),
319 ITEM_FACTORY_ENTRY("/Analyze/Apply as Filter/_Not Selected", NULL, match_selected_ptree_cb,
320 MATCH_SELECTED_NOT|MATCH_SELECTED_APPLY_NOW, NULL, NULL),
321 ITEM_FACTORY_ENTRY("/Analyze/Apply as Filter/... _and Selected", NULL, match_selected_ptree_cb,
322 MATCH_SELECTED_AND|MATCH_SELECTED_APPLY_NOW, NULL, NULL),
323 ITEM_FACTORY_ENTRY("/Analyze/Apply as Filter/... _or Selected", NULL, match_selected_ptree_cb,
324 MATCH_SELECTED_OR|MATCH_SELECTED_APPLY_NOW, NULL, NULL),
325 ITEM_FACTORY_ENTRY("/Analyze/Apply as Filter/... a_nd not Selected", NULL, match_selected_ptree_cb,
326 MATCH_SELECTED_AND_NOT|MATCH_SELECTED_APPLY_NOW, NULL, NULL),
327 ITEM_FACTORY_ENTRY("/Analyze/Apply as Filter/... o_r not Selected", NULL, match_selected_ptree_cb,
328 MATCH_SELECTED_OR_NOT|MATCH_SELECTED_APPLY_NOW, NULL, NULL),
329 ITEM_FACTORY_ENTRY("/Analyze/_Prepare a Filter", NULL, NULL, 0, "<Branch>", NULL),
330 ITEM_FACTORY_ENTRY("/Analyze/Prepare a Filter/_Selected", NULL, match_selected_ptree_cb,
331 MATCH_SELECTED_REPLACE, NULL, NULL),
332 ITEM_FACTORY_ENTRY("/Analyze/Prepare a Filter/_Not Selected", NULL, match_selected_ptree_cb,
333 MATCH_SELECTED_NOT, NULL, NULL),
334 ITEM_FACTORY_ENTRY("/Analyze/Prepare a Filter/... _and Selected", NULL, match_selected_ptree_cb,
335 MATCH_SELECTED_AND, NULL, NULL),
336 ITEM_FACTORY_ENTRY("/Analyze/Prepare a Filter/... _or Selected", NULL, match_selected_ptree_cb,
337 MATCH_SELECTED_OR, NULL, NULL),
338 ITEM_FACTORY_ENTRY("/Analyze/Prepare a Filter/... a_nd not Selected", NULL, match_selected_ptree_cb,
339 MATCH_SELECTED_AND_NOT, NULL, NULL),
340 ITEM_FACTORY_ENTRY("/Analyze/Prepare a Filter/... o_r not Selected", NULL, match_selected_ptree_cb,
341 MATCH_SELECTED_OR_NOT, NULL, NULL),
342 ITEM_FACTORY_ENTRY("/Analyze/<separator>", NULL, NULL, 0, "<Separator>", NULL),
343 ITEM_FACTORY_ENTRY("/Analyze/_Enabled Protocols...", "<shift><control>R", proto_cb, 0, NULL, NULL),
344 ITEM_FACTORY_ENTRY("/Analyze/Decode _As...", NULL, decode_as_cb,
346 ITEM_FACTORY_ENTRY("/Analyze/_User Specified Decodes...", NULL,
347 decode_show_cb, 0, NULL, NULL),
348 ITEM_FACTORY_ENTRY("/Analyze/<separator>", NULL, NULL, 0, "<Separator>", NULL),
349 ITEM_FACTORY_ENTRY("/Analyze/_Follow TCP Stream", NULL,
350 follow_stream_cb, 0, NULL, NULL),
351 ITEM_FACTORY_ENTRY("/_Statistics", NULL, NULL, 0, "<Branch>", NULL),
352 ITEM_FACTORY_STOCK_ENTRY("/Statistics/_Summary", NULL, summary_open_cb, 0, GTK_STOCK_PROPERTIES),
353 ITEM_FACTORY_ENTRY("/Statistics/_Protocol Hierarchy", NULL,
354 proto_hier_stats_cb, 0, NULL, NULL),
355 ITEM_FACTORY_STOCK_ENTRY("/Statistics/Conversations", NULL,
356 init_conversation_notebook_cb, 0, ETHEREAL_STOCK_CONVERSATIONS),
357 ITEM_FACTORY_STOCK_ENTRY("/Statistics/Endpoints", NULL,
358 init_hostlist_notebook_cb, 0, ETHEREAL_STOCK_ENDPOINTS),
359 ITEM_FACTORY_ENTRY("/_Help", NULL, NULL, 0, "<Branch>", NULL),
360 ITEM_FACTORY_STOCK_ENTRY("/Help/_Contents", "F1", topic_menu_cb, HELP_CONTENT, GTK_STOCK_HELP),
361 ITEM_FACTORY_ENTRY("/Help/_Supported Protocols", NULL, supported_cb, 0, NULL, NULL),
362 #if (GLIB_MAJOR_VERSION >= 2)
363 #ifdef ETHEREAL_EUG_DIR
364 ITEM_FACTORY_ENTRY("/Help/User's Guide", NULL, url_page_menu_cb, HELP_CONTENT, NULL, NULL),
366 ITEM_FACTORY_ENTRY("/Help/Manual Pages", NULL, NULL, 0, "<Branch>", NULL),
367 ITEM_FACTORY_ENTRY("/Help/Manual Pages/Ethereal", NULL, topic_menu_cb, LOCALPAGE_MAN_ETHEREAL, NULL, NULL),
368 ITEM_FACTORY_ENTRY("/Help/Manual Pages/Ethereal Filter", NULL, topic_menu_cb, LOCALPAGE_MAN_ETHEREAL_FILTER, NULL, NULL),
369 ITEM_FACTORY_ENTRY("/Help/Manual Pages/<separator>", NULL, NULL, 0, "<Separator>", NULL),
370 ITEM_FACTORY_ENTRY("/Help/Manual Pages/Tethereal", NULL, topic_menu_cb, LOCALPAGE_MAN_TETHEREAL, NULL, NULL),
371 ITEM_FACTORY_ENTRY("/Help/Manual Pages/Mergecap", NULL, topic_menu_cb, LOCALPAGE_MAN_MERGECAP, NULL, NULL),
372 ITEM_FACTORY_ENTRY("/Help/Manual Pages/Editcap", NULL, topic_menu_cb, LOCALPAGE_MAN_EDITCAP, NULL, NULL),
373 ITEM_FACTORY_ENTRY("/Help/Manual Pages/Text2pcap", NULL, topic_menu_cb, LOCALPAGE_MAN_TEXT2PCAP, NULL, NULL),
374 ITEM_FACTORY_ENTRY("/Help/Ethereal Online", NULL, NULL, 0, "<Branch>", NULL),
375 ITEM_FACTORY_STOCK_ENTRY("/Help/Ethereal Online/Home Page", NULL, topic_menu_cb, ONLINEPAGE_HOME, GTK_STOCK_HOME),
376 ITEM_FACTORY_STOCK_ENTRY("/Help/Ethereal Online/Wiki", NULL, topic_menu_cb, ONLINEPAGE_WIKI, ETHEREAL_STOCK_WIKI),
377 ITEM_FACTORY_STOCK_ENTRY("/Help/Ethereal Online/User's Guide", NULL, topic_menu_cb, ONLINEPAGE_USERGUIDE, ETHEREAL_STOCK_WEB_SUPPORT),
378 ITEM_FACTORY_ENTRY("/Help/Ethereal Online/FAQ's", NULL, topic_menu_cb, ONLINEPAGE_FAQ, NULL, NULL),
379 ITEM_FACTORY_ENTRY("/Help/Ethereal Online/Downloads", NULL, topic_menu_cb, ONLINEPAGE_DOWNLOAD, NULL, NULL),
380 ITEM_FACTORY_ENTRY("/Help/Ethereal Online/Example Files", NULL, topic_menu_cb, ONLINEPAGE_SAMPLE_FILES, NULL, NULL),
382 ITEM_FACTORY_ENTRY("/Help/<separator>", NULL, NULL, 0, "<Separator>", NULL),
383 ITEM_FACTORY_STOCK_ENTRY("/Help/_About Ethereal", NULL, about_ethereal_cb,
384 0, ETHEREAL_STOCK_ABOUT)
388 /* calculate the number of menu_items */
389 static int nmenu_items = sizeof(menu_items) / sizeof(menu_items[0]);
391 /* packet list popup */
392 static GtkItemFactoryEntry packet_list_menu_items[] =
394 ITEM_FACTORY_ENTRY("/Mark Packet (toggle)", NULL, mark_frame_cb, 0, NULL, NULL),
395 ITEM_FACTORY_ENTRY("/Time Reference", NULL, NULL, 0, "<Branch>", NULL),
396 ITEM_FACTORY_STOCK_ENTRY("/Time Reference/Set Time Reference (toggle)", NULL, reftime_frame_cb, REFTIME_TOGGLE, ETHEREAL_STOCK_TIME),
397 ITEM_FACTORY_ENTRY("/Time Reference/Find Next", NULL, reftime_frame_cb, REFTIME_FIND_NEXT, NULL, NULL),
398 ITEM_FACTORY_ENTRY("/Time Reference/Find Previous", NULL, reftime_frame_cb, REFTIME_FIND_PREV, NULL, NULL),
400 ITEM_FACTORY_ENTRY("/<separator>", NULL, NULL, 0, "<Separator>", NULL),
402 ITEM_FACTORY_ENTRY("/Apply as Filter", NULL, NULL, 0, "<Branch>", NULL),
403 ITEM_FACTORY_ENTRY("/Apply as Filter/_Selected", NULL, match_selected_plist_cb,
404 MATCH_SELECTED_REPLACE|MATCH_SELECTED_APPLY_NOW, NULL, NULL),
405 ITEM_FACTORY_ENTRY("/Apply as Filter/_Not Selected", NULL, match_selected_plist_cb,
406 MATCH_SELECTED_NOT|MATCH_SELECTED_APPLY_NOW, NULL, NULL),
407 ITEM_FACTORY_ENTRY("/Apply as Filter/... _and Selected", NULL, match_selected_plist_cb,
408 MATCH_SELECTED_AND|MATCH_SELECTED_APPLY_NOW, NULL, NULL),
409 ITEM_FACTORY_ENTRY("/Apply as Filter/... _or Selected", NULL, match_selected_plist_cb,
410 MATCH_SELECTED_OR|MATCH_SELECTED_APPLY_NOW, NULL, NULL),
411 ITEM_FACTORY_ENTRY("/Apply as Filter/... a_nd not Selected", NULL, match_selected_plist_cb,
412 MATCH_SELECTED_AND_NOT|MATCH_SELECTED_APPLY_NOW, NULL, NULL),
413 ITEM_FACTORY_ENTRY("/Apply as Filter/... o_r not Selected", NULL, match_selected_plist_cb,
414 MATCH_SELECTED_OR_NOT|MATCH_SELECTED_APPLY_NOW, NULL, NULL),
416 ITEM_FACTORY_ENTRY("/Prepare a Filter", NULL, NULL, 0, "<Branch>", NULL),
417 ITEM_FACTORY_ENTRY("/Prepare a Filter/_Selected", NULL, match_selected_plist_cb,
418 MATCH_SELECTED_REPLACE, NULL, NULL),
419 ITEM_FACTORY_ENTRY("/Prepare a Filter/_Not Selected", NULL, match_selected_plist_cb,
420 MATCH_SELECTED_NOT, NULL, NULL),
421 ITEM_FACTORY_ENTRY("/Prepare a Filter/... _and Selected", NULL, match_selected_plist_cb,
422 MATCH_SELECTED_AND, NULL, NULL),
423 ITEM_FACTORY_ENTRY("/Prepare a Filter/... _or Selected", NULL, match_selected_plist_cb,
424 MATCH_SELECTED_OR, NULL, NULL),
425 ITEM_FACTORY_ENTRY("/Prepare a Filter/... a_nd not Selected", NULL, match_selected_plist_cb,
426 MATCH_SELECTED_AND_NOT, NULL, NULL),
427 ITEM_FACTORY_ENTRY("/Prepare a Filter/... o_r not Selected", NULL, match_selected_plist_cb,
428 MATCH_SELECTED_OR_NOT, NULL, NULL),
430 ITEM_FACTORY_ENTRY("/Follow TCP Stream", NULL, follow_stream_cb,
433 ITEM_FACTORY_ENTRY("/<separator>", NULL, NULL, 0, "<Separator>", NULL),
435 ITEM_FACTORY_ENTRY("/Decode As...", NULL, decode_as_cb, 0, NULL, NULL),
436 ITEM_FACTORY_ENTRY("/Print...", NULL, file_print_selected_cmd_cb, 0, NULL, NULL),
437 ITEM_FACTORY_ENTRY("/Show Packet in New Window", NULL, new_window_cb,
441 static GtkItemFactoryEntry tree_view_menu_items[] =
443 ITEM_FACTORY_ENTRY("/Expand Subtrees", NULL, expand_tree_cb, 0, NULL, NULL),
444 ITEM_FACTORY_ENTRY("/Expand All", NULL, expand_all_cb, 0, NULL, NULL),
445 ITEM_FACTORY_ENTRY("/Collapse All", NULL, collapse_all_cb, 0, NULL, NULL),
447 ITEM_FACTORY_ENTRY("/<separator>", NULL, NULL, 0, "<Separator>", NULL),
449 ITEM_FACTORY_ENTRY("/Apply as Filter", NULL, NULL, 0, "<Branch>", NULL),
450 ITEM_FACTORY_ENTRY("/Apply as Filter/_Selected", NULL, match_selected_ptree_cb,
451 MATCH_SELECTED_REPLACE|MATCH_SELECTED_APPLY_NOW, NULL, NULL),
452 ITEM_FACTORY_ENTRY("/Apply as Filter/_Not Selected", NULL, match_selected_ptree_cb,
453 MATCH_SELECTED_NOT|MATCH_SELECTED_APPLY_NOW, NULL, NULL),
454 ITEM_FACTORY_ENTRY("/Apply as Filter/... _and Selected", NULL, match_selected_ptree_cb,
455 MATCH_SELECTED_AND|MATCH_SELECTED_APPLY_NOW, NULL, NULL),
456 ITEM_FACTORY_ENTRY("/Apply as Filter/... _or Selected", NULL, match_selected_ptree_cb,
457 MATCH_SELECTED_OR|MATCH_SELECTED_APPLY_NOW, NULL, NULL),
458 ITEM_FACTORY_ENTRY("/Apply as Filter/... a_nd not Selected", NULL, match_selected_ptree_cb,
459 MATCH_SELECTED_AND_NOT|MATCH_SELECTED_APPLY_NOW, NULL, NULL),
460 ITEM_FACTORY_ENTRY("/Apply as Filter/... o_r not Selected", NULL, match_selected_ptree_cb,
461 MATCH_SELECTED_OR_NOT|MATCH_SELECTED_APPLY_NOW, NULL, NULL),
463 ITEM_FACTORY_ENTRY("/Prepare a Filter", NULL, NULL, 0, "<Branch>", NULL),
464 ITEM_FACTORY_ENTRY("/Prepare a Filter/_Selected", NULL, match_selected_ptree_cb,
465 MATCH_SELECTED_REPLACE, NULL, NULL),
466 ITEM_FACTORY_ENTRY("/Prepare a Filter/_Not Selected", NULL, match_selected_ptree_cb,
467 MATCH_SELECTED_NOT, NULL, NULL),
468 ITEM_FACTORY_ENTRY("/Prepare a Filter/... _and Selected", NULL, match_selected_ptree_cb,
469 MATCH_SELECTED_AND, NULL, NULL),
470 ITEM_FACTORY_ENTRY("/Prepare a Filter/... _or Selected", NULL, match_selected_ptree_cb,
471 MATCH_SELECTED_OR, NULL, NULL),
472 ITEM_FACTORY_ENTRY("/Prepare a Filter/... a_nd not Selected", NULL, match_selected_ptree_cb,
473 MATCH_SELECTED_AND_NOT, NULL, NULL),
474 ITEM_FACTORY_ENTRY("/Prepare a Filter/... o_r not Selected", NULL, match_selected_ptree_cb,
475 MATCH_SELECTED_OR_NOT, NULL, NULL),
477 ITEM_FACTORY_ENTRY("/Follow TCP Stream", NULL, follow_stream_cb,
480 ITEM_FACTORY_ENTRY("/<separator>", NULL, NULL, 0, "<Separator>", NULL),
482 ITEM_FACTORY_STOCK_ENTRY("/Wiki Protocol Page", NULL, selected_ptree_info_cb,
483 0, ETHEREAL_STOCK_WIKI),
484 ITEM_FACTORY_STOCK_ENTRY("/Filter Field Reference", NULL, selected_ptree_ref_cb,
485 0, ETHEREAL_STOCK_INTERNET),
486 ITEM_FACTORY_ENTRY("/Protocol Preferences...", NULL, properties_cb,
488 ITEM_FACTORY_ENTRY("/<separator>", NULL, NULL, 0, "<Separator>", NULL),
489 ITEM_FACTORY_ENTRY("/Decode As...", NULL, decode_as_cb, 0, NULL, NULL),
490 ITEM_FACTORY_ENTRY("/_Resolve Name", NULL, resolve_name_cb, 0, NULL, NULL),
491 ITEM_FACTORY_ENTRY("/_Go to Corresponding Packet", NULL, goto_framenum_cb, 0, NULL, NULL),
494 static GtkItemFactoryEntry hexdump_menu_items[] =
496 ITEM_FACTORY_ENTRY("/Copy", NULL, copy_hex_cb,
498 ITEM_FACTORY_ENTRY("/Export Selected Packet Bytes...", NULL, savehex_cb,
502 static int initialize = TRUE;
503 static GtkItemFactory *main_menu_factory = NULL;
504 static GtkItemFactory *packet_list_menu_factory = NULL;
505 static GtkItemFactory *tree_view_menu_factory = NULL;
506 static GtkItemFactory *hexdump_menu_factory = NULL;
508 static GSList *popup_menu_list = NULL;
510 static GtkAccelGroup *grp;
513 main_menu_new(GtkAccelGroup ** table) {
516 grp = gtk_accel_group_new();
521 menubar = main_menu_factory->widget;
535 packet_list_menu_factory = gtk_item_factory_new(GTK_TYPE_MENU, "<main>", NULL);
536 popup_menu_object = gtk_menu_new();
537 gtk_item_factory_create_items_ac(packet_list_menu_factory, sizeof(packet_list_menu_items)/sizeof(packet_list_menu_items[0]), packet_list_menu_items, popup_menu_object, 2);
538 OBJECT_SET_DATA(popup_menu_object, PM_PACKET_LIST_KEY,
539 packet_list_menu_factory->widget);
540 popup_menu_list = g_slist_append((GSList *)popup_menu_list, packet_list_menu_factory);
542 tree_view_menu_factory = gtk_item_factory_new(GTK_TYPE_MENU, "<main>", NULL);
543 gtk_item_factory_create_items_ac(tree_view_menu_factory, sizeof(tree_view_menu_items)/sizeof(tree_view_menu_items[0]), tree_view_menu_items, popup_menu_object, 2);
544 OBJECT_SET_DATA(popup_menu_object, PM_TREE_VIEW_KEY,
545 tree_view_menu_factory->widget);
546 popup_menu_list = g_slist_append((GSList *)popup_menu_list, tree_view_menu_factory);
548 hexdump_menu_factory = gtk_item_factory_new(GTK_TYPE_MENU, "<main>", NULL);
549 gtk_item_factory_create_items_ac(hexdump_menu_factory, sizeof(hexdump_menu_items)/sizeof(hexdump_menu_items[0]), hexdump_menu_items, popup_menu_object, 2);
550 OBJECT_SET_DATA(popup_menu_object, PM_HEXDUMP_KEY,
551 hexdump_menu_factory->widget);
552 popup_menu_list = g_slist_append((GSList *)popup_menu_list, hexdump_menu_factory);
555 main_menu_factory = gtk_item_factory_new(GTK_TYPE_MENU_BAR, "<main>", grp);
556 gtk_item_factory_create_items_ac(main_menu_factory, nmenu_items, menu_items, NULL, 2);
558 merge_all_tap_menus(tap_menu_tree_root);
560 /* Initialize enabled/disabled state of menu items */
561 set_menus_for_unsaved_capture_file(FALSE);
562 set_menus_for_capture_file(FALSE);
564 /* Un-#if this when we actually implement Cut/Copy/Paste.
565 Then make sure you enable them when they can be done. */
566 set_menu_sensitivity(main_menu_factory, "/Edit/Cut", FALSE);
567 set_menu_sensitivity(main_menu_factory, "/Edit/Copy", FALSE);
568 set_menu_sensitivity(main_menu_factory, "/Edit/Paste", FALSE);
571 set_menus_for_captured_packets(FALSE);
572 set_menus_for_selected_packet(&cfile);
573 set_menus_for_selected_tree_row(&cfile);
574 set_menus_for_capture_in_progress(FALSE);
576 /* init with an empty recent files list */
577 clear_menu_recent_capture_file_cmd_cb(NULL, NULL);
582 gint tap_menu_item_add_compare(gconstpointer a, gconstpointer b)
585 ((const menu_item_t *) a)->name,
586 ((const menu_item_t *) b)->name);
590 /* add a menuitem below the current node */
591 GList * tap_menu_item_add(
594 GtkItemFactoryCallback callback,
595 gboolean (*selected_packet_enabled)(frame_data *, epan_dissect_t *),
596 gboolean (*selected_tree_row_enabled)(field_info *),
597 gpointer callback_data,
604 child = g_malloc(sizeof (menu_item_t));
605 child->group = group;
607 child->callback = callback;
608 child->selected_packet_enabled = selected_packet_enabled;
609 child->selected_tree_row_enabled = selected_tree_row_enabled;
610 child->callback_data = callback_data;
611 child->enabled = FALSE;
612 child->children = NULL;
614 /* insert the new child node into the parent */
615 curr = curnode->data;
616 curr->children = g_list_insert_sorted(curr->children, child, tap_menu_item_add_compare);
618 /* return the new node */
619 /* XXX: improve this */
620 return g_list_find(curr->children, child);
624 * Add a new menu item for a tap.
625 * This must be called after we've created the main menu, so it can't
626 * be called from the routine that registers taps - we have to introduce
627 * another per-tap registration routine.
629 * "callback" gets called when the menu item is selected; it should do
630 * the work of creating the tap window.
632 * "selected_packet_enabled" gets called by "set_menus_for_selected_packet()";
633 * it's passed a Boolean that's TRUE if a packet is selected and FALSE
634 * otherwise, and should return TRUE if the tap will work now (which
635 * might depend on whether a packet is selected and, if one is, on the
636 * packet) and FALSE if not.
638 * "selected_tree_row_enabled" gets called by
639 * "set_menus_for_selected_tree_row()"; it's passed a Boolean that's TRUE if
640 * a protocol tree row is selected and FALSE otherwise, and should return
641 * TRUE if the tap will work now (which might depend on whether a tree row
642 * is selected and, if one is, on the tree row) and FALSE if not.
645 register_tap_menu_item(
647 REGISTER_TAP_GROUP_E group,
648 GtkItemFactoryCallback callback,
649 gboolean (*selected_packet_enabled)(frame_data *, epan_dissect_t *),
650 gboolean (*selected_tree_row_enabled)(field_info *),
651 gpointer callback_data)
653 /*static const char toolspath[] = "/Statistics/";*/
663 * The menu path must be relative.
665 g_assert(*name != '/');
668 case(REGISTER_TAP_GROUP_GENERIC): toolspath = "/Statistics/"; break;
669 case(REGISTER_TAP_GROUP_CONVERSATION_LIST): toolspath = "/Statistics/_Conversation List/"; break;
670 case(REGISTER_TAP_GROUP_ENDPOINT_LIST): toolspath = "/Statistics/_Endpoint List/"; break;
671 case(REGISTER_TAP_GROUP_RESPONSE_TIME): toolspath = "/Statistics/Service _Response Time/"; break;
672 case(REGISTER_TAP_GROUP_TELEPHONY): toolspath = "/Statistics/"; break;
673 case(REGISTER_TAP_GROUP_NONE): toolspath = "/Statistics/"; break;
679 /* add the (empty) root node, if not already done */
680 if(tap_menu_tree_root == NULL) {
681 child = g_malloc0(sizeof (menu_item_t));
682 tap_menu_tree_root = g_list_append(NULL, child);
686 * Create any submenus required.
688 curnode = tap_menu_tree_root;
690 while ((p = strchr(p, '/')) != NULL) {
692 * OK, everything between "name" and "p" is
693 * a menu relative subtree into which the menu item
696 * Construct the absolute path name of that subtree.
698 menupathlen = strlen(toolspath) + 1 + (p - name);
699 menupath = g_malloc(menupathlen);
700 strcpy(menupath, toolspath);
701 strncat(menupath, name, p - name);
704 * Does there exist an entry with that path at this
705 * level of the Analyze menu tree?
707 child = curnode->data;
708 for (childnode = child->children; childnode != NULL; childnode = childnode->next) {
709 child = childnode->data;
710 if (strcmp(child->name, menupath) == 0)
713 if (childnode == NULL) {
715 * No. Create such an item as a subtree, and
716 * add it to the Tools menu tree.
718 childnode = tap_menu_item_add(
719 menupath, group, NULL, NULL ,NULL, NULL, curnode);
722 * Yes. We don't need this "menupath" any longer.
729 * Skip over the '/' we found.
735 * Construct the main menu path for the menu item.
737 menupathlen = strlen(toolspath) + 1 + strlen(name);
738 menupath = g_malloc(menupathlen);
739 strcpy(menupath, toolspath);
740 strcat(menupath, name);
743 * Construct an item factory entry for the item, and add it to
747 menupath, group, callback,
748 selected_packet_enabled, selected_tree_row_enabled,
749 callback_data, curnode);
753 guint merge_tap_menus_layered(GList *node, gint group) {
754 GtkItemFactoryEntry *entry;
757 menu_item_t *node_data = node->data;
760 * Is this a leaf node or an interior node?
762 if (node_data->children == NULL) {
768 * The root node doesn't correspond to a menu tree item; it
769 * has a null name pointer.
771 if (node_data->name != NULL && group == node_data->group) {
772 entry = g_malloc0(sizeof (GtkItemFactoryEntry));
773 entry->path = node_data->name;
774 entry->callback = node_data->callback;
775 #if GTK_MAJOR_VERSION >= 2
777 case(REGISTER_TAP_GROUP_NONE):
779 case(REGISTER_TAP_GROUP_GENERIC):
781 case(REGISTER_TAP_GROUP_CONVERSATION_LIST):
782 entry->item_type = "<StockItem>";
783 entry->extra_data = ETHEREAL_STOCK_CONVERSATIONS;
785 case(REGISTER_TAP_GROUP_ENDPOINT_LIST):
786 entry->item_type = "<StockItem>";
787 entry->extra_data = ETHEREAL_STOCK_ENDPOINTS;
789 case(REGISTER_TAP_GROUP_RESPONSE_TIME):
790 entry->item_type = "<StockItem>";
791 entry->extra_data = ETHEREAL_STOCK_TIME;
793 case(REGISTER_TAP_GROUP_TELEPHONY):
794 entry->item_type = "<StockItem>";
795 entry->extra_data = ETHEREAL_STOCK_TELEPHONY;
798 g_assert_not_reached();
801 gtk_item_factory_create_item(main_menu_factory, entry, node_data->callback_data, 2);
802 set_menu_sensitivity(main_menu_factory, node_data->name, FALSE); /* no capture file yet */
807 * It's an interior node; call
808 * "merge_tap_menus_layered()" on all its children
812 * The root node doesn't correspond to a menu tree item; it
813 * has a null name pointer.
815 if (node_data->name != NULL && group == node_data->group) {
816 entry = g_malloc0(sizeof (GtkItemFactoryEntry));
817 entry->path = node_data->name;
818 entry->item_type = "<Branch>";
819 gtk_item_factory_create_item(main_menu_factory, entry,
821 set_menu_sensitivity(main_menu_factory, node_data->name,
822 FALSE); /* no children yet */
826 for (child = node_data->children; child != NULL; child =
828 added += merge_tap_menus_layered(child, group);
836 void merge_all_tap_menus(GList *node) {
837 GtkItemFactoryEntry *entry;
839 entry = g_malloc0(sizeof (GtkItemFactoryEntry));
840 entry->item_type = "<Separator>";
841 entry->path = "/Statistics/";
844 * merge only the menu items of the specific group,
845 * and then append a seperator
847 if (merge_tap_menus_layered(node, REGISTER_TAP_GROUP_GENERIC)) {
848 gtk_item_factory_create_item(main_menu_factory, entry, NULL, 2);
850 if (merge_tap_menus_layered(node, REGISTER_TAP_GROUP_CONVERSATION_LIST)) {
851 /*gtk_item_factory_create_item(main_menu_factory, entry, NULL, 2);*/
853 if (merge_tap_menus_layered(node, REGISTER_TAP_GROUP_ENDPOINT_LIST)) {
854 /*gtk_item_factory_create_item(main_menu_factory, entry, NULL, 2);*/
856 if (merge_tap_menus_layered(node, REGISTER_TAP_GROUP_RESPONSE_TIME)) {
857 gtk_item_factory_create_item(main_menu_factory, entry, NULL, 2);
859 if (merge_tap_menus_layered(node, REGISTER_TAP_GROUP_TELEPHONY)) {
860 gtk_item_factory_create_item(main_menu_factory, entry, NULL, 2);
862 if (merge_tap_menus_layered(node, REGISTER_TAP_GROUP_NONE)) {
863 /*gtk_item_factory_create_item(main_menu_factory, entry, NULL, 2);*/
870 * Enable/disable menu sensitivity.
873 set_menu_sensitivity(GtkItemFactory *ifactory, const gchar *path, gint val)
876 GtkWidget *menu_item;
881 /* the underscore character regularly confuses things, as it will prevent finding
882 * the menu_item, so it has to be removed first */
883 dup = g_strdup(path);
894 if (ifactory == NULL) {
896 * Do it for all pop-up menus.
898 for (menu_list = popup_menu_list; menu_list != NULL;
899 menu_list = g_slist_next(menu_list))
900 set_menu_sensitivity(menu_list->data, dup, val);
903 * Do it for that particular menu.
905 if ((menu_item = gtk_item_factory_get_widget(ifactory, dup)) != NULL) {
906 if (GTK_IS_MENU(menu_item)) {
908 * "dup" refers to a submenu; "gtk_item_factory_get_widget()"
909 * gets the menu, not the item that, when selected, pops up
912 * We have to change the latter item's sensitivity, so that
913 * it shows up normally if sensitive and grayed-out if
916 menu_item = gtk_menu_get_attach_widget(GTK_MENU(menu_item));
918 gtk_widget_set_sensitive(menu_item, val);
920 /* be sure this menu item *is* existing */
921 g_assert_not_reached();
929 set_menu_object_data_meat(GtkItemFactory *ifactory, gchar *path, gchar *key, gpointer data)
931 GtkWidget *menu = NULL;
933 if ((menu = gtk_item_factory_get_widget(ifactory, path)) != NULL)
934 OBJECT_SET_DATA(menu, key, data);
938 set_menu_object_data (gchar *path, gchar *key, gpointer data) {
939 GSList *menu_list = popup_menu_list;
940 gchar *shortpath = strrchr(path, '/');
942 set_menu_object_data_meat(main_menu_factory, path, key, data);
943 while (menu_list != NULL) {
944 set_menu_object_data_meat(menu_list->data, shortpath, key, data);
945 menu_list = g_slist_next(menu_list);
950 /* Recently used capture files submenu:
951 * Submenu containing the recently used capture files.
952 * The capture filenames are always kept with the absolute path, to be independant
953 * of the current path.
954 * They are only stored inside the labels of the submenu (no separate list). */
956 #define MENU_RECENT_FILES_PATH "/File/Open Recent"
957 #define MENU_RECENT_FILES_KEY "Recent File Name"
960 update_menu_recent_capture_file1(GtkWidget *widget, gpointer cnt) {
961 gchar *widget_cf_name;
963 widget_cf_name = OBJECT_GET_DATA(widget, MENU_RECENT_FILES_KEY);
965 /* if this menu item is a file, count it */
966 if (widget_cf_name) {
972 /* update the menu */
974 update_menu_recent_capture_file(GtkWidget *submenu_recent_files) {
977 gtk_container_foreach(GTK_CONTAINER(submenu_recent_files),
978 update_menu_recent_capture_file1, &cnt);
980 /* make parent menu item sensitive only, if we have any valid files in the list */
981 set_menu_sensitivity(main_menu_factory, MENU_RECENT_FILES_PATH, cnt);
985 /* remove the capture filename from the "Recent Files" menu */
987 remove_menu_recent_capture_file(GtkWidget *widget, gpointer unused _U_) {
988 GtkWidget *submenu_recent_files;
989 gchar *widget_cf_name;
992 widget_cf_name = OBJECT_GET_DATA(widget, MENU_RECENT_FILES_KEY);
993 g_free(widget_cf_name);
995 /* get the submenu container item */
996 submenu_recent_files = gtk_item_factory_get_widget(main_menu_factory, MENU_RECENT_FILES_PATH);
998 /* XXX: is this all we need to do, to free the menu item and its label?
999 The reference count of widget will go to 0, so it'll be freed;
1000 will that free the label? */
1001 gtk_container_remove(GTK_CONTAINER(submenu_recent_files), widget);
1005 /* callback, if the user pushed the <Clear File List> item */
1007 clear_menu_recent_capture_file_cmd_cb(GtkWidget *w _U_, gpointer unused _U_) {
1008 GtkWidget *submenu_recent_files;
1011 submenu_recent_files = gtk_item_factory_get_widget(main_menu_factory, MENU_RECENT_FILES_PATH);
1013 gtk_container_foreach(GTK_CONTAINER(submenu_recent_files),
1014 remove_menu_recent_capture_file, NULL);
1016 update_menu_recent_capture_file(submenu_recent_files);
1020 /* callback, if the user pushed a recent file submenu item */
1022 menu_open_recent_file_cmd(GtkWidget *w)
1024 GtkWidget *submenu_recent_files;
1025 GtkWidget *menu_item_child;
1029 submenu_recent_files = gtk_item_factory_get_widget(main_menu_factory, MENU_RECENT_FILES_PATH);
1031 /* get capture filename from the menu item label */
1032 menu_item_child = (GTK_BIN(w))->child;
1033 gtk_label_get(GTK_LABEL(menu_item_child), &cf_name);
1035 /* open and read the capture file (this will close an existing file) */
1036 if (cf_open(&cfile, cf_name, FALSE, &err) == CF_OK) {
1039 /* the capture file isn't existing any longer, remove menu item */
1040 /* XXX: ask user to remove item, it's maybe only a temporary problem */
1041 remove_menu_recent_capture_file(w, NULL);
1044 update_menu_recent_capture_file(submenu_recent_files);
1047 static void menu_open_recent_file_answered_cb(gpointer dialog _U_, gint btn, gpointer data _U_)
1051 /* save file first */
1052 file_save_as_cmd(after_save_open_recent_file, data);
1056 menu_open_recent_file_cmd(data);
1058 case(ESD_BTN_CANCEL):
1061 g_assert_not_reached();
1066 menu_open_recent_file_cmd_cb(GtkWidget *widget, gpointer data _U_) {
1070 if((cfile.state != FILE_CLOSED) && !cfile.user_saved && prefs.gui_ask_unsaved) {
1071 /* user didn't saved his current file, ask him */
1072 dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_YES_NO_CANCEL,
1073 PRIMARY_TEXT_START "Save capture file before opening a new one?" PRIMARY_TEXT_END "\n\n"
1074 "If you open a new capture file without saving, your current capture data will be discarded.");
1075 simple_dialog_set_cb(dialog, menu_open_recent_file_answered_cb, widget);
1077 /* unchanged file */
1078 menu_open_recent_file_cmd(widget);
1082 /* add the capture filename (with an absolute path) to the "Recent Files" menu */
1084 add_menu_recent_capture_file_absolute(gchar *cf_name) {
1085 GtkWidget *submenu_recent_files;
1086 GList *menu_item_list;
1088 gchar *widget_cf_name;
1089 gchar *normalized_cf_name;
1090 GtkWidget *menu_item;
1095 normalized_cf_name = g_strdup(cf_name);
1097 /* replace all slashes by backslashes */
1098 g_strdelimit(normalized_cf_name, "/", '\\');
1101 /* get the submenu container item */
1102 submenu_recent_files = gtk_item_factory_get_widget(main_menu_factory, MENU_RECENT_FILES_PATH);
1104 /* convert container to a GList */
1105 menu_item_list = gtk_container_children(GTK_CONTAINER(submenu_recent_files));
1107 /* iterate through list items of menu_item_list,
1108 * removing special items, a maybe duplicate entry and every item above count_max */
1110 for (li = g_list_first(menu_item_list); li; li = li->next, cnt++) {
1111 /* get capture filename */
1112 menu_item = GTK_WIDGET(li->data);
1113 widget_cf_name = OBJECT_GET_DATA(menu_item, MENU_RECENT_FILES_KEY);
1115 /* if this element string is one of our special items (seperator, ...) or
1116 * already in the list or
1117 * this element is above maximum count (too old), remove it */
1118 if (!widget_cf_name ||
1120 /* do a case insensitive compare on win32 */
1121 #if GLIB_MAJOR_VERSION < 2
1122 g_strncasecmp(widget_cf_name, normalized_cf_name, 1000) == 0 ||
1124 g_ascii_strncasecmp(widget_cf_name, normalized_cf_name, 1000) == 0 ||
1127 /* do a case sensitive compare on unix */
1128 strncmp(widget_cf_name, normalized_cf_name, 1000) == 0 ||
1130 cnt >= prefs.gui_recent_files_count_max) {
1131 remove_menu_recent_capture_file(li->data, NULL);
1136 g_list_free(menu_item_list);
1138 /* add new item at latest position */
1139 menu_item = gtk_menu_item_new_with_label(normalized_cf_name);
1140 OBJECT_SET_DATA(menu_item, MENU_RECENT_FILES_KEY, normalized_cf_name);
1141 gtk_menu_prepend (GTK_MENU(submenu_recent_files), menu_item);
1142 SIGNAL_CONNECT_OBJECT(GTK_OBJECT(menu_item), "activate",
1143 menu_open_recent_file_cmd_cb, (GtkObject *) menu_item);
1144 gtk_widget_show (menu_item);
1146 /* add seperator at last position */
1147 menu_item = gtk_menu_item_new();
1148 gtk_menu_append (GTK_MENU(submenu_recent_files), menu_item);
1149 gtk_widget_show (menu_item);
1151 /* add new "clear list" item at last position */
1152 #if GTK_MAJOR_VERSION < 2
1153 menu_item = gtk_menu_item_new_with_label("<Clear File List>");
1155 menu_item = gtk_image_menu_item_new_from_stock(GTK_STOCK_CLEAR, NULL);
1157 gtk_menu_append (GTK_MENU(submenu_recent_files), menu_item);
1158 SIGNAL_CONNECT_OBJECT(GTK_OBJECT(menu_item), "activate",
1159 clear_menu_recent_capture_file_cmd_cb, (GtkObject *) menu_item);
1160 gtk_widget_show (menu_item);
1162 update_menu_recent_capture_file(submenu_recent_files);
1166 /* add the capture filename to the "Recent Files" menu */
1167 /* (will change nothing, if this filename is already in the menu) */
1169 add_menu_recent_capture_file(gchar *cf_name) {
1174 /* if this filename is an absolute path, we can use it directly */
1175 if (g_path_is_absolute(cf_name)) {
1176 add_menu_recent_capture_file_absolute(cf_name);
1180 /* this filename is not an absolute path, prepend the current dir */
1181 curr = g_get_current_dir();
1182 absolute = g_strdup_printf("%s%s%s", curr, G_DIR_SEPARATOR_S, cf_name);
1183 add_menu_recent_capture_file_absolute(absolute);
1189 /* write all capture filenames of the menu to the user's recent file */
1191 menu_recent_file_write_all(FILE *rf) {
1192 GtkWidget *submenu_recent_files;
1198 submenu_recent_files = gtk_item_factory_get_widget(main_menu_factory, MENU_RECENT_FILES_PATH);
1200 /* we have to iterate backwards through the children's list,
1201 * so we get the latest item last in the file.
1202 * (don't use gtk_container_foreach() here, it will return the wrong iteration order) */
1203 children = gtk_container_children(GTK_CONTAINER(submenu_recent_files));
1204 child = g_list_last(children);
1205 while(child != NULL) {
1206 /* get capture filename from the menu item label */
1207 cf_name = OBJECT_GET_DATA(child->data, MENU_RECENT_FILES_KEY);
1209 fprintf (rf, RECENT_KEY_CAPTURE_FILE ": %s\n", cf_name);
1212 child = g_list_previous(child);
1215 g_list_free(children);
1220 main_toolbar_show_cb(GtkWidget *w _U_, gpointer d _U_)
1223 /* save current setting in recent */
1224 recent.main_toolbar_show = GTK_CHECK_MENU_ITEM(w)->active;
1226 main_widgets_show_or_hide();
1231 filter_toolbar_show_cb(GtkWidget *w _U_, gpointer d _U_)
1234 /* save current setting in recent */
1235 recent.filter_toolbar_show = GTK_CHECK_MENU_ITEM(w)->active;
1237 main_widgets_show_or_hide();
1242 packet_list_show_cb(GtkWidget *w _U_, gpointer d _U_)
1245 /* save current setting in recent */
1246 recent.packet_list_show = GTK_CHECK_MENU_ITEM(w)->active;
1248 main_widgets_show_or_hide();
1253 tree_view_show_cb(GtkWidget *w _U_, gpointer d _U_)
1256 /* save current setting in recent */
1257 recent.tree_view_show = GTK_CHECK_MENU_ITEM(w)->active;
1259 main_widgets_show_or_hide();
1264 byte_view_show_cb(GtkWidget *w _U_, gpointer d _U_)
1267 /* save current setting in recent */
1268 recent.byte_view_show = GTK_CHECK_MENU_ITEM(w)->active;
1270 main_widgets_show_or_hide();
1275 statusbar_show_cb(GtkWidget *w _U_, gpointer d _U_)
1278 /* save current setting in recent */
1279 recent.statusbar_show = GTK_CHECK_MENU_ITEM(w)->active;
1281 main_widgets_show_or_hide();
1286 timestamp_absolute_cb(GtkWidget *w _U_, gpointer d _U_)
1288 if (recent.gui_time_format != TS_ABSOLUTE) {
1289 set_timestamp_setting(TS_ABSOLUTE);
1290 recent.gui_time_format = TS_ABSOLUTE;
1291 cf_change_time_formats(&cfile);
1296 timestamp_absolute_date_cb(GtkWidget *w _U_, gpointer d _U_)
1298 if (recent.gui_time_format != TS_ABSOLUTE_WITH_DATE) {
1299 set_timestamp_setting(TS_ABSOLUTE_WITH_DATE);
1300 recent.gui_time_format = TS_ABSOLUTE_WITH_DATE;
1301 cf_change_time_formats(&cfile);
1306 timestamp_relative_cb(GtkWidget *w _U_, gpointer d _U_)
1308 if (recent.gui_time_format != TS_RELATIVE) {
1309 set_timestamp_setting(TS_RELATIVE);
1310 recent.gui_time_format = TS_RELATIVE;
1311 cf_change_time_formats(&cfile);
1316 timestamp_delta_cb(GtkWidget *w _U_, gpointer d _U_)
1318 if (recent.gui_time_format != TS_DELTA) {
1319 set_timestamp_setting(TS_DELTA);
1320 recent.gui_time_format = TS_DELTA;
1321 cf_change_time_formats(&cfile);
1326 menu_name_resolution_changed(void)
1328 GtkWidget *menu = NULL;
1330 menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Name Resolution/Enable for MAC Layer");
1331 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), g_resolv_flags & RESOLV_MAC);
1333 menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Name Resolution/Enable for Network Layer");
1334 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), g_resolv_flags & RESOLV_NETWORK);
1336 menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Name Resolution/Enable for Transport Layer");
1337 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), g_resolv_flags & RESOLV_TRANSPORT);
1341 name_resolution_mac_cb(GtkWidget *w _U_, gpointer d _U_)
1343 if (GTK_CHECK_MENU_ITEM(w)->active) {
1344 g_resolv_flags |= RESOLV_MAC;
1346 g_resolv_flags &= ~RESOLV_MAC;
1351 name_resolution_network_cb(GtkWidget *w _U_, gpointer d _U_)
1353 if (GTK_CHECK_MENU_ITEM(w)->active) {
1354 g_resolv_flags |= RESOLV_NETWORK;
1356 g_resolv_flags &= ~RESOLV_NETWORK;
1361 name_resolution_transport_cb(GtkWidget *w _U_, gpointer d _U_)
1363 if (GTK_CHECK_MENU_ITEM(w)->active) {
1364 g_resolv_flags |= RESOLV_TRANSPORT;
1366 g_resolv_flags &= ~RESOLV_TRANSPORT;
1372 menu_auto_scroll_live_changed(gboolean auto_scroll_live_in) {
1376 /* tell menu about it */
1377 menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Auto Scroll in Live Capture");
1378 if( ((gboolean) GTK_CHECK_MENU_ITEM(menu)->active) != auto_scroll_live_in) {
1379 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), auto_scroll_live_in);
1382 /* tell toolbar about it */
1383 toolbar_auto_scroll_live_changed(auto_scroll_live_in);
1385 /* change auto scroll */
1386 if(auto_scroll_live_in != auto_scroll_live) {
1387 auto_scroll_live = auto_scroll_live_in;
1392 auto_scroll_live_cb(GtkWidget *w _U_, gpointer d _U_)
1394 menu_auto_scroll_live_changed(GTK_CHECK_MENU_ITEM(w)->active);
1400 menu_colorize_changed(gboolean packet_list_colorize) {
1404 /* tell menu about it */
1405 menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Colorize Packet List");
1406 if( ((gboolean) GTK_CHECK_MENU_ITEM(menu)->active) != packet_list_colorize) {
1407 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), packet_list_colorize);
1410 /* tell toolbar about it */
1411 toolbar_colorize_changed(packet_list_colorize);
1413 /* change colorization */
1414 if(packet_list_colorize != recent.packet_list_colorize) {
1415 recent.packet_list_colorize = packet_list_colorize;
1416 color_filters_enable(packet_list_colorize);
1417 cf_colorize_packets(&cfile);
1422 colorize_cb(GtkWidget *w, gpointer d _U_)
1424 menu_colorize_changed(GTK_CHECK_MENU_ITEM(w)->active);
1428 /* the recent file read has finished, update the menu corresponding */
1430 menu_recent_read_finished(void) {
1431 GtkWidget *menu = NULL;
1433 menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Main Toolbar");
1434 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), recent.main_toolbar_show);
1436 menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Filter Toolbar");
1437 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), recent.filter_toolbar_show);
1439 menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Statusbar");
1440 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), recent.statusbar_show);
1442 menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Packet List");
1443 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), recent.packet_list_show);
1445 menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Packet Details");
1446 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), recent.tree_view_show);
1448 menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Packet Bytes");
1449 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), recent.byte_view_show);
1451 menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Colorize Packet List");
1452 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), recent.packet_list_colorize);
1454 menu_name_resolution_changed();
1457 menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Auto Scroll in Live Capture");
1458 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), auto_scroll_live);
1461 main_widgets_rearrange();
1463 /* don't change the time format, if we had a command line value */
1464 if (get_timestamp_setting() != TS_NOT_SET) {
1465 recent.gui_time_format = get_timestamp_setting();
1468 switch(recent.gui_time_format) {
1470 menu = gtk_item_factory_get_widget(main_menu_factory,
1471 "/View/Time Display Format/Time of Day");
1472 /* set_active will not trigger the callback when activating an active item! */
1473 recent.gui_time_format = -1;
1474 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), FALSE);
1475 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), TRUE);
1477 case(TS_ABSOLUTE_WITH_DATE):
1478 menu = gtk_item_factory_get_widget(main_menu_factory,
1479 "/View/Time Display Format/Date and Time of Day");
1480 recent.gui_time_format = -1;
1481 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), TRUE);
1484 menu = gtk_item_factory_get_widget(main_menu_factory,
1485 "/View/Time Display Format/Seconds Since Beginning of Capture");
1486 recent.gui_time_format = -1;
1487 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), TRUE);
1490 menu = gtk_item_factory_get_widget(main_menu_factory,
1491 "/View/Time Display Format/Seconds Since Previous Packet");
1492 recent.gui_time_format = -1;
1493 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), TRUE);
1496 g_assert_not_reached();
1499 menu_colorize_changed(recent.packet_list_colorize);
1504 popup_menu_handler(GtkWidget *widget, GdkEvent *event, gpointer data)
1506 GtkWidget *menu = (GtkWidget *)data;
1507 GdkEventButton *event_button = NULL;
1510 if(widget == NULL || event == NULL || data == NULL) {
1515 * If we ever want to make the menu differ based on what row
1516 * and/or column we're above, we'd use "eth_clist_get_selection_info()"
1517 * to find the row and column number for the coordinates; a CTree is,
1518 * I guess, like a CList with one column(?) and the expander widget
1521 /* Check if we are on packet_list object */
1522 if (widget == OBJECT_GET_DATA(popup_menu_object, E_MPACKET_LIST_KEY)) {
1523 if (packet_list_get_event_row_column(widget, (GdkEventButton *)event,
1525 OBJECT_SET_DATA(popup_menu_object, E_MPACKET_LIST_ROW_KEY,
1526 GINT_TO_POINTER(row));
1527 OBJECT_SET_DATA(popup_menu_object, E_MPACKET_LIST_COL_KEY,
1528 GINT_TO_POINTER(column));
1529 packet_list_set_selected_row(row);
1533 /* Check if we are on tree_view object */
1534 if (widget == tree_view) {
1535 tree_view_select(widget, (GdkEventButton *) event);
1538 /* Check if we are on byte_view object */
1539 if(widget == get_notebook_bv_ptr(byte_nb_ptr)) {
1540 byte_view_select(widget, (GdkEventButton *) event);
1543 /* context menu handler (but the byte view notebook pages have their own handler) */
1544 if(event->type == GDK_BUTTON_PRESS && widget != byte_nb_ptr) {
1545 event_button = (GdkEventButton *) event;
1547 /* To qoute the "Gdk Event Structures" doc:
1548 * "Normally button 1 is the left mouse button, 2 is the middle button, and 3 is the right button" */
1549 if(event_button->button == 3) {
1550 gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL,
1551 event_button->button,
1552 event_button->time);
1553 SIGNAL_EMIT_STOP_BY_NAME(widget, "button_press_event");
1557 #if GTK_MAJOR_VERSION >= 2
1558 /* GDK_2BUTTON_PRESS is a doubleclick -> expand/collapse tree row */
1559 /* GTK version 1 seems to be doing this automatically */
1560 if (widget == tree_view && event->type == GDK_2BUTTON_PRESS) {
1563 if (gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(widget),
1564 (gint) (((GdkEventButton *)event)->x),
1565 (gint) (((GdkEventButton *)event)->y),
1566 &path, NULL, NULL, NULL))
1568 if (gtk_tree_view_row_expanded(GTK_TREE_VIEW(widget), path))
1569 gtk_tree_view_collapse_row(GTK_TREE_VIEW(widget), path);
1571 gtk_tree_view_expand_row(GTK_TREE_VIEW(widget), path,
1573 gtk_tree_path_free(path);
1580 /* Enable or disable menu items based on whether you have a capture file
1581 you've finished reading. */
1583 set_menus_for_capture_file(gboolean have_capture_file)
1585 set_menu_sensitivity(main_menu_factory, "/File/Open...", have_capture_file);
1586 set_menu_sensitivity(main_menu_factory, "/File/Open Recent", have_capture_file);
1587 set_menu_sensitivity(main_menu_factory, "/File/Merge...", have_capture_file);
1588 set_menu_sensitivity(main_menu_factory, "/File/Close", have_capture_file);
1589 set_menu_sensitivity(main_menu_factory, "/File/Save As...",
1591 set_menu_sensitivity(main_menu_factory, "/File/Export", have_capture_file);
1592 set_menu_sensitivity(main_menu_factory, "/View/Reload", have_capture_file);
1593 set_toolbar_for_capture_file(have_capture_file);
1594 packets_bar_update();
1597 /* Enable or disable menu items based on whether you have an unsaved
1598 capture file you've finished reading. */
1600 set_menus_for_unsaved_capture_file(gboolean have_unsaved_capture_file)
1602 set_menu_sensitivity(main_menu_factory, "/File/Save",
1603 have_unsaved_capture_file);
1604 set_toolbar_for_unsaved_capture_file(have_unsaved_capture_file);
1607 /* Enable or disable menu items based on whether there's a capture in
1610 set_menus_for_capture_in_progress(gboolean capture_in_progress)
1612 set_menu_sensitivity(main_menu_factory, "/File/Open...",
1613 !capture_in_progress);
1614 set_menu_sensitivity(main_menu_factory, "/File/Open Recent",
1615 !capture_in_progress);
1617 set_menu_sensitivity(main_menu_factory, "/Capture/Options...",
1618 !capture_in_progress);
1619 set_menu_sensitivity(main_menu_factory, "/Capture/Start",
1620 !capture_in_progress);
1621 set_menu_sensitivity(main_menu_factory, "/Capture/Stop",
1622 capture_in_progress);
1623 set_menu_sensitivity(main_menu_factory, "/Capture/Restart",
1624 capture_in_progress);
1625 set_toolbar_for_capture_in_progress(capture_in_progress);
1627 set_capture_if_dialog_for_capture_in_progress(capture_in_progress);
1628 #endif /* HAVE_LIBPCAP */
1631 /* Enable or disable menu items based on whether you have some captured
1634 walk_menu_tree_for_captured_packets(GList *node,
1635 gboolean have_captured_packets)
1637 gboolean is_enabled;
1639 menu_item_t *node_data = node->data;
1642 * Is this a leaf node or an interior node?
1644 if (node_data->children == NULL) {
1648 * If it has no "selected_packet_enabled()" or
1649 * "selected_tree_row_enabled()" routines, we enable
1650 * it. This allows tap windows to be popped up even
1651 * if you have no capture file; this is done to let
1652 * the user pop up multiple tap windows before reading
1653 * in a capture file, so that they can be processed in
1654 * parallel while the capture file is being read rather
1655 * than one at at time as you pop up the windows, and to
1656 * let the user pop up tap windows before starting an
1657 * "Update list of packets in real time" capture, so that
1658 * the statistics can be displayed while the capture is
1661 * If it has either of those routines, we disable it for
1662 * now - as long as, when a capture is first available,
1663 * we don't get called after a packet or tree row is
1664 * selected, that's OK.
1665 * XXX - that should be done better.
1667 if (node_data->selected_packet_enabled == NULL &&
1668 node_data->selected_tree_row_enabled == NULL)
1669 node_data->enabled = TRUE;
1671 node_data->enabled = FALSE;
1674 * It's an interior node; call
1675 * "walk_menu_tree_for_captured_packets()" on all its
1676 * children and, if any of them are enabled, enable
1677 * this node, otherwise disable it.
1679 * XXX - should we just leave all interior nodes enabled?
1680 * Which is a better UI choice?
1683 for (child = node_data->children; child != NULL; child =
1685 if (walk_menu_tree_for_captured_packets(child,
1686 have_captured_packets))
1689 node_data->enabled = is_enabled;
1693 * The root node doesn't correspond to a menu tree item; it
1694 * has a null name pointer.
1696 if (node_data->name != NULL) {
1697 set_menu_sensitivity(main_menu_factory, node_data->name,
1698 node_data->enabled);
1700 return node_data->enabled;
1704 set_menus_for_captured_packets(gboolean have_captured_packets)
1706 set_menu_sensitivity(main_menu_factory, "/File/Print...",
1707 have_captured_packets);
1708 set_menu_sensitivity(packet_list_menu_factory, "/Print...",
1709 have_captured_packets);
1710 set_menu_sensitivity(main_menu_factory, "/Edit/Find Packet...",
1711 have_captured_packets);
1712 set_menu_sensitivity(main_menu_factory, "/Edit/Find Next",
1713 have_captured_packets);
1714 set_menu_sensitivity(main_menu_factory, "/Edit/Find Previous",
1715 have_captured_packets);
1716 set_menu_sensitivity(main_menu_factory, "/View/Zoom In",
1717 have_captured_packets);
1718 set_menu_sensitivity(main_menu_factory, "/View/Zoom Out",
1719 have_captured_packets);
1720 set_menu_sensitivity(main_menu_factory, "/View/Normal Size",
1721 have_captured_packets);
1722 set_menu_sensitivity(main_menu_factory, "/Go/Go to Packet...",
1723 have_captured_packets);
1724 set_menu_sensitivity(main_menu_factory, "/Go/First Packet",
1725 have_captured_packets);
1726 set_menu_sensitivity(main_menu_factory, "/Go/Last Packet",
1727 have_captured_packets);
1728 set_menu_sensitivity(main_menu_factory, "/Statistics/Summary",
1729 have_captured_packets);
1730 set_menu_sensitivity(main_menu_factory, "/Statistics/Protocol Hierarchy",
1731 have_captured_packets);
1733 walk_menu_tree_for_captured_packets(tap_menu_tree_root,
1734 have_captured_packets);
1735 set_toolbar_for_captured_packets(have_captured_packets);
1736 packets_bar_update();
1739 /* Enable or disable menu items based on whether a packet is selected and,
1740 if so, on the properties of the packet. */
1742 walk_menu_tree_for_selected_packet(GList *node, frame_data *fd,
1743 epan_dissect_t *edt)
1745 gboolean is_enabled;
1747 menu_item_t *node_data = node->data;
1750 * Is this a leaf node or an interior node?
1752 if (node_data->children == NULL) {
1756 * If it has no "selected_packet_enabled()" routine,
1757 * leave its enabled/disabled status alone - it
1758 * doesn't depend on whether we have a packet selected
1759 * or not or on the selected packet.
1761 * If it has a "selected_packet_enabled()" routine,
1762 * call it and set the item's enabled/disabled status
1763 * based on its return value.
1765 if (node_data->selected_packet_enabled != NULL)
1766 node_data->enabled = node_data->selected_packet_enabled(fd, edt);
1769 * It's an interior node; call
1770 * "walk_menu_tree_for_selected_packet()" on all its
1771 * children and, if any of them are enabled, enable
1772 * this node, otherwise disable it.
1774 * XXX - should we just leave all interior nodes enabled?
1775 * Which is a better UI choice?
1778 for (child = node_data->children; child != NULL; child =
1780 if (walk_menu_tree_for_selected_packet(child, fd, edt))
1783 node_data->enabled = is_enabled;
1787 * The root node doesn't correspond to a menu tree item; it
1788 * has a null name pointer.
1790 if (node_data->name != NULL) {
1791 set_menu_sensitivity(main_menu_factory, node_data->name,
1792 node_data->enabled);
1794 return node_data->enabled;
1798 set_menus_for_selected_packet(capture_file *cf)
1800 set_menu_sensitivity(main_menu_factory, "/Edit/Mark Packet (toggle)",
1801 cf->current_frame != NULL);
1802 set_menu_sensitivity(packet_list_menu_factory, "/Mark Packet (toggle)",
1803 cf->current_frame != NULL);
1804 set_menu_sensitivity(main_menu_factory, "/Edit/Time Reference",
1805 cf->current_frame != NULL);
1806 set_menu_sensitivity(packet_list_menu_factory, "/Time Reference",
1807 cf->current_frame != NULL);
1808 set_menu_sensitivity(main_menu_factory, "/Edit/Mark All Packets",
1809 cf->current_frame != NULL);
1810 set_menu_sensitivity(main_menu_factory, "/Edit/Unmark All Packets",
1811 cf->current_frame != NULL);
1812 set_menu_sensitivity(main_menu_factory, "/View/Resize All Columns",
1813 cf->current_frame != NULL);
1814 set_menu_sensitivity(main_menu_factory, "/View/Collapse All",
1815 cf->current_frame != NULL);
1816 set_menu_sensitivity(tree_view_menu_factory, "/Collapse All",
1817 cf->current_frame != NULL);
1818 set_menu_sensitivity(main_menu_factory, "/View/Expand All",
1819 cf->current_frame != NULL);
1820 set_menu_sensitivity(tree_view_menu_factory, "/Expand All",
1821 cf->current_frame != NULL);
1822 set_menu_sensitivity(main_menu_factory, "/View/Show Packet in New Window",
1823 cf->current_frame != NULL);
1824 set_menu_sensitivity(packet_list_menu_factory, "/Show Packet in New Window",
1825 cf->current_frame != NULL);
1826 set_menu_sensitivity(main_menu_factory, "/Analyze/Follow TCP Stream",
1827 cf->current_frame != NULL ? (cf->edt->pi.ipproto == IP_PROTO_TCP) : FALSE);
1828 set_menu_sensitivity(packet_list_menu_factory, "/Follow TCP Stream",
1829 cf->current_frame != NULL ? (cf->edt->pi.ipproto == IP_PROTO_TCP) : FALSE);
1830 set_menu_sensitivity(tree_view_menu_factory, "/Follow TCP Stream",
1831 cf->current_frame != NULL ? (cf->edt->pi.ipproto == IP_PROTO_TCP) : FALSE);
1832 set_menu_sensitivity(main_menu_factory, "/Analyze/Decode As...",
1833 cf->current_frame != NULL && decode_as_ok());
1834 set_menu_sensitivity(packet_list_menu_factory, "/Decode As...",
1835 cf->current_frame != NULL && decode_as_ok());
1836 set_menu_sensitivity(tree_view_menu_factory, "/Decode As...",
1837 cf->current_frame != NULL && decode_as_ok());
1838 set_menu_sensitivity(main_menu_factory, "/View/Name Resolution/Resolve Name",
1839 cf->current_frame != NULL && (g_resolv_flags & RESOLV_ALL_ADDRS) != RESOLV_ALL_ADDRS);
1840 set_menu_sensitivity(tree_view_menu_factory, "/Resolve Name",
1841 cf->current_frame != NULL && (g_resolv_flags & RESOLV_ALL_ADDRS) != RESOLV_ALL_ADDRS);
1842 set_menu_sensitivity(packet_list_menu_factory, "/Apply as Filter",
1843 cf->current_frame != NULL);
1844 set_menu_sensitivity(packet_list_menu_factory, "/Prepare a Filter",
1845 cf->current_frame != NULL);
1847 walk_menu_tree_for_selected_packet(tap_menu_tree_root, cf->current_frame,
1849 packets_bar_update();
1852 /* Enable or disable menu items based on whether a tree row is selected
1853 and, if so, on the properties of the tree row. */
1855 walk_menu_tree_for_selected_tree_row(GList *node, field_info *fi)
1857 gboolean is_enabled;
1859 menu_item_t *node_data = node->data;
1862 * Is this a leaf node or an interior node?
1864 if (node_data->children == NULL) {
1868 * If it has no "selected_tree_row_enabled()" routine,
1869 * leave its enabled/disabled status alone - it
1870 * doesn't depend on whether we have a tree row selected
1871 * or not or on the selected tree row.
1873 * If it has a "selected_tree_row_enabled()" routine,
1874 * call it and set the item's enabled/disabled status
1875 * based on its return value.
1877 if (node_data->selected_tree_row_enabled != NULL)
1878 node_data->enabled = node_data->selected_tree_row_enabled(fi);
1881 * It's an interior node; call
1882 * "walk_menu_tree_for_selected_tree_row()" on all its
1883 * children and, if any of them are enabled, enable
1884 * this node, otherwise disable it.
1886 * XXX - should we just leave all interior nodes enabled?
1887 * Which is a better UI choice?
1890 for (child = node_data->children; child != NULL; child =
1892 if (walk_menu_tree_for_selected_tree_row(child, fi))
1895 node_data->enabled = is_enabled;
1899 * The root node doesn't correspond to a menu tree item; it
1900 * has a null name pointer.
1902 if (node_data->name != NULL) {
1903 set_menu_sensitivity(main_menu_factory, node_data->name,
1904 node_data->enabled);
1906 return node_data->enabled;
1910 set_menus_for_selected_tree_row(capture_file *cf)
1912 gboolean properties;
1915 set_menu_sensitivity(main_menu_factory, "/File/Export/Selected Packet Bytes...",
1916 cf->finfo_selected != NULL);
1917 set_menu_sensitivity(hexdump_menu_factory, "/Copy",
1918 cf->finfo_selected != NULL);
1919 set_menu_sensitivity(hexdump_menu_factory, "/Export Selected Packet Bytes...",
1920 cf->finfo_selected != NULL);
1922 if (cf->finfo_selected != NULL) {
1923 header_field_info *hfinfo = cf->finfo_selected->hfinfo;
1924 if (hfinfo->parent == -1) {
1925 properties = prefs_is_registered_protocol(hfinfo->abbrev);
1927 properties = prefs_is_registered_protocol(proto_registrar_get_abbrev(hfinfo->parent));
1929 set_menu_sensitivity(main_menu_factory,
1930 "/Go/Go to Corresponding Packet", hfinfo->type == FT_FRAMENUM);
1931 set_menu_sensitivity(tree_view_menu_factory,
1932 "/Go to Corresponding Packet", hfinfo->type == FT_FRAMENUM);
1933 set_menu_sensitivity(main_menu_factory, "/Analyze/Apply as Filter",
1934 proto_can_match_selected(cf->finfo_selected, cf->edt));
1935 set_menu_sensitivity(tree_view_menu_factory, "/Apply as Filter",
1936 proto_can_match_selected(cf->finfo_selected, cf->edt));
1937 set_menu_sensitivity(main_menu_factory, "/Analyze/Prepare a Filter",
1938 proto_can_match_selected(cf->finfo_selected, cf->edt));
1939 set_menu_sensitivity(tree_view_menu_factory, "/Prepare a Filter",
1940 proto_can_match_selected(cf->finfo_selected, cf->edt));
1941 set_menu_sensitivity(tree_view_menu_factory, "/Protocol Preferences...",
1943 set_menu_sensitivity(main_menu_factory, "/View/Expand Tree", cf->finfo_selected->tree_type != -1);
1944 set_menu_sensitivity(tree_view_menu_factory, "/Wiki Protocol Page",
1946 set_menu_sensitivity(tree_view_menu_factory, "/Filter Field Reference",
1949 set_menu_sensitivity(main_menu_factory,
1950 "/Go/Go to Corresponding Packet", FALSE);
1951 set_menu_sensitivity(tree_view_menu_factory,
1952 "/Go to Corresponding Packet", FALSE);
1953 set_menu_sensitivity(main_menu_factory, "/Analyze/Apply as Filter", FALSE);
1954 set_menu_sensitivity(tree_view_menu_factory, "/Apply as Filter", FALSE);
1955 set_menu_sensitivity(main_menu_factory, "/Analyze/Prepare a Filter", FALSE);
1956 set_menu_sensitivity(tree_view_menu_factory, "/Prepare a Filter", FALSE);
1957 set_menu_sensitivity(tree_view_menu_factory, "/Protocol Preferences...",
1959 set_menu_sensitivity(main_menu_factory, "/View/Expand Tree", FALSE);
1960 set_menu_sensitivity(tree_view_menu_factory, "/Wiki Protocol Page",
1962 set_menu_sensitivity(tree_view_menu_factory, "/Filter Field Reference",
1966 walk_menu_tree_for_selected_tree_row(tap_menu_tree_root, cf->finfo_selected);
1969 void set_menus_for_packet_history(gboolean back_history, gboolean forward_history) {
1971 set_menu_sensitivity(main_menu_factory, "/Go/Back", back_history);
1972 set_menu_sensitivity(main_menu_factory, "/Go/Forward", forward_history);
1974 set_toolbar_for_packet_history(back_history, forward_history);