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"
49 #include "fileset_dlg.h"
52 #include "summary_dlg.h"
53 #include "prefs_dlg.h"
54 #include "packet_win.h"
56 #include "follow_dlg.h"
57 #include "decode_as_dlg.h"
59 #include "supported_protos_dlg.h"
60 #include "proto_dlg.h"
61 #include "proto_hier_stats_dlg.h"
63 #include <epan/plugins.h>
64 #include <epan/epan_dissect.h>
65 #include "compat_macros.h"
67 #include "gtkglobals.h"
70 #include "packet_list.h"
73 #include "../ui_util.h"
74 #include "proto_draw.h"
75 #include "conversations_table.h"
76 #include "hostlist_table.h"
77 #include "simple_dialog.h"
78 #include "packet_history.h"
79 #include "color_filters.h"
81 GtkWidget *popup_menu_object;
84 clear_menu_recent_capture_file_cmd_cb(GtkWidget *w, gpointer unused _U_);
86 typedef struct _menu_item {
90 GtkItemFactoryCallback callback;
91 gpointer callback_data;
92 gboolean (*selected_packet_enabled)(frame_data *, epan_dissect_t *);
93 gboolean (*selected_tree_row_enabled)(field_info *);
97 static GList *tap_menu_tree_root = NULL;
100 merge_all_tap_menus(GList *node);
102 #define GTK_MENU_FUNC(a) ((GtkItemFactoryCallback)(a))
104 static void menus_init(void);
105 static void set_menu_sensitivity (GtkItemFactory *, const gchar *, gint);
106 static void main_toolbar_show_cb(GtkWidget *w _U_, gpointer d _U_);
107 static void filter_toolbar_show_cb(GtkWidget *w _U_, gpointer d _U_);
108 static void packet_list_show_cb(GtkWidget *w _U_, gpointer d _U_);
109 static void tree_view_show_cb(GtkWidget *w _U_, gpointer d _U_);
110 static void byte_view_show_cb(GtkWidget *w _U_, gpointer d _U_);
111 static void statusbar_show_cb(GtkWidget *w _U_, gpointer d _U_);
112 static void timestamp_absolute_cb(GtkWidget *w _U_, gpointer d _U_);
113 static void timestamp_absolute_date_cb(GtkWidget *w _U_, gpointer d _U_);
114 static void timestamp_relative_cb(GtkWidget *w _U_, gpointer d _U_);
115 static void timestamp_delta_cb(GtkWidget *w _U_, gpointer d _U_);
116 static void name_resolution_mac_cb(GtkWidget *w _U_, gpointer d _U_);
117 static void name_resolution_network_cb(GtkWidget *w _U_, gpointer d _U_);
118 static void name_resolution_transport_cb(GtkWidget *w _U_, gpointer d _U_);
120 static void auto_scroll_live_cb(GtkWidget *w _U_, gpointer d _U_);
122 static void colorize_cb(GtkWidget *w _U_, gpointer d _U_);
124 /* This is the GtkItemFactoryEntry structure used to generate new menus.
125 Item 1: The menu path. The letter after the underscore indicates an
126 accelerator key once the menu is open.
127 Item 2: The accelerator key for the entry
128 Item 3: The callback function.
129 Item 4: The callback action. This changes the parameters with
130 which the function is called. The default is 0.
131 Item 5: The item type, used to define what kind of an item it is.
132 Here are the possible values:
136 "<Title>" -> create a title item
137 "<Item>" -> create a simple item
138 "<ImageItem>" -> create an item holding an image (gtk2)
139 "<StockItem>" -> create an item holding a stock image (gtk2)
140 "<CheckItem>" -> create a check item
141 "<ToggleItem>" -> create a toggle item
142 "<RadioItem>" -> create a radio item
143 <path> -> path of a radio item to link against
144 "<Separator>" -> create a separator
145 "<Tearoff>" -> create a tearoff separator (gtk2)
146 "<Branch>" -> create an item to hold sub items (optional)
147 "<LastBranch>" -> create a right justified branch
148 Item 6: extra data needed for ImageItem and StockItem (gtk2)
151 /* As a general GUI guideline, we try to follow the Gnome Human Interface Guidelines, which can be found at:
152 http://developer.gnome.org/projects/gup/hig/1.0/index.html
154 Please note: there are some differences between the Gnome HIG menu suggestions and our implementation:
156 File/Open Recent: the Gnome HIG suggests putting the list of recently used files as elements into the File menuitem.
157 As this is ok for only a few items, this will become unhandy for 10 or even more list entries.
158 For this reason, we use a submenu for this.
160 File/Close: the Gnome HIG suggests putting this item just above the Quit item.
161 This results in unintuitive behaviour as both Close and Quit items are very near together.
162 By putting the Close item near the open item(s), it better suggests that it will close the
163 currently opened/captured file only.
168 static GtkItemFactoryEntry menu_items[] =
170 ITEM_FACTORY_ENTRY("/_File", NULL, NULL, 0, "<Branch>", NULL),
171 ITEM_FACTORY_STOCK_ENTRY("/File/_Open...", "<control>O", file_open_cmd_cb,
173 ITEM_FACTORY_ENTRY("/File/Open _Recent", NULL, NULL, 0, "<Branch>", NULL),
174 ITEM_FACTORY_ENTRY("/File/_Merge...", NULL, file_merge_cmd_cb, 0, NULL, NULL),
175 ITEM_FACTORY_STOCK_ENTRY("/File/_Close", "<control>W", file_close_cmd_cb,
177 ITEM_FACTORY_ENTRY("/File/<separator>", NULL, NULL, 0, "<Separator>", NULL),
178 ITEM_FACTORY_STOCK_ENTRY("/File/_Save", "<control>S", file_save_cmd_cb,
180 ITEM_FACTORY_STOCK_ENTRY("/File/Save _As...", "<shift><control>S", file_save_as_cmd_cb,
181 0, GTK_STOCK_SAVE_AS),
182 ITEM_FACTORY_ENTRY("/File/<separator>", NULL, NULL, 0, "<Separator>", NULL),
183 ITEM_FACTORY_ENTRY("/File/File Set", NULL, NULL, 0, "<Branch>", NULL),
184 ITEM_FACTORY_STOCK_ENTRY("/File/File Set/List Files", NULL, fileset_cb, 0, ETHEREAL_STOCK_FILE_SET_LIST),
185 ITEM_FACTORY_STOCK_ENTRY("/File/File Set/Next File", NULL, fileset_next_cb, 0, ETHEREAL_STOCK_FILE_SET_NEXT),
186 ITEM_FACTORY_STOCK_ENTRY("/File/File Set/Previous File", NULL, fileset_previous_cb, 0, ETHEREAL_STOCK_FILE_SET_PREVIOUS),
187 ITEM_FACTORY_ENTRY("/File/<separator>", NULL, NULL, 0, "<Separator>", NULL),
188 ITEM_FACTORY_ENTRY("/File/_Export", NULL, NULL, 0, "<Branch>", NULL),
189 ITEM_FACTORY_ENTRY("/File/Export/as \"Plain _Text\" file...", NULL, export_text_cmd_cb,
191 ITEM_FACTORY_ENTRY("/File/Export/as \"_PostScript\" file...", NULL, export_ps_cmd_cb,
193 ITEM_FACTORY_ENTRY("/File/Export/as \"_CSV\" (Comma Separated Values packet summary) file...",
194 NULL, export_csv_cmd_cb, 0, NULL, NULL),
195 ITEM_FACTORY_ENTRY("/File/Export/<separator>", NULL, NULL, 0, "<Separator>", NULL),
196 ITEM_FACTORY_ENTRY("/File/Export/as XML - \"P_SML\" (packet summary) file...", NULL, export_psml_cmd_cb,
198 ITEM_FACTORY_ENTRY("/File/Export/as XML - \"P_DML\" (packet details) file...", NULL, export_pdml_cmd_cb,
200 ITEM_FACTORY_ENTRY("/File/Export/<separator>", NULL, NULL, 0, "<Separator>", NULL),
201 ITEM_FACTORY_ENTRY("/File/Export/Selected Packet _Bytes...", "<control>H", savehex_cb,
203 ITEM_FACTORY_ENTRY("/File/<separator>", NULL, NULL, 0, "<Separator>", NULL),
204 ITEM_FACTORY_STOCK_ENTRY("/File/_Print...", "<control>P", file_print_cmd_cb,
206 ITEM_FACTORY_ENTRY("/File/<separator>", NULL, NULL, 0, "<Separator>", NULL),
207 ITEM_FACTORY_STOCK_ENTRY("/File/_Quit", "<control>Q", file_quit_cmd_cb,
209 ITEM_FACTORY_ENTRY("/_Edit", NULL, NULL, 0, "<Branch>", NULL),
211 /* Un-#if this when we actually implement Cut/Copy/Paste. */
212 ITEM_FACTORY_STOCK_ENTRY("/Edit/Cut", "<control>X", NULL,
214 ITEM_FACTORY_STOCK_ENTRY("/Edit/Copy", "<control>C", NULL,
216 ITEM_FACTORY_STOCK_ENTRY("/Edit/Paste", "<control>V", NULL,
218 ITEM_FACTORY_ENTRY("/Edit/<separator>", NULL, NULL, 0, "<Separator>"),
220 ITEM_FACTORY_STOCK_ENTRY("/Edit/_Find Packet...", "<control>F",
221 find_frame_cb, 0, GTK_STOCK_FIND),
222 ITEM_FACTORY_ENTRY("/Edit/Find Ne_xt", "<control>N", find_next_cb, 0, NULL, NULL),
223 ITEM_FACTORY_ENTRY("/Edit/Find Pre_vious", "<control>B", find_previous_cb, 0, NULL, NULL),
224 ITEM_FACTORY_ENTRY("/Edit/<separator>", NULL, NULL, 0, "<Separator>", NULL),
225 ITEM_FACTORY_ENTRY("/Edit/_Time Reference", NULL, NULL, 0, "<Branch>", NULL),
226 ITEM_FACTORY_STOCK_ENTRY("/Edit/Time Reference/Set Time Reference (toggle)", "<control>T", reftime_frame_cb,
227 REFTIME_TOGGLE, ETHEREAL_STOCK_TIME),
228 ITEM_FACTORY_ENTRY("/Edit/Time Reference/Find Next", NULL, reftime_frame_cb, REFTIME_FIND_NEXT, NULL, NULL),
229 ITEM_FACTORY_ENTRY("/Edit/Time Reference/Find Previous", NULL, reftime_frame_cb, REFTIME_FIND_PREV, NULL, NULL),
230 ITEM_FACTORY_ENTRY("/Edit/_Mark Packet (toggle)", "<control>M", mark_frame_cb,
232 ITEM_FACTORY_ENTRY("/Edit/Mark _All Packets", NULL, mark_all_frames_cb,
234 ITEM_FACTORY_ENTRY("/Edit/_Unmark All Packets", NULL, unmark_all_frames_cb,
236 ITEM_FACTORY_ENTRY("/Edit/<separator>", NULL, NULL, 0, "<Separator>", NULL),
237 ITEM_FACTORY_STOCK_ENTRY("/Edit/_Preferences...", "<shift><control>P", prefs_cb,
238 0, GTK_STOCK_PREFERENCES),
239 ITEM_FACTORY_ENTRY("/_View", NULL, NULL, 0, "<Branch>", NULL),
240 ITEM_FACTORY_ENTRY("/View/_Main Toolbar", NULL, main_toolbar_show_cb, 0, "<CheckItem>", NULL),
241 ITEM_FACTORY_ENTRY("/View/_Filter Toolbar", NULL, filter_toolbar_show_cb, 0, "<CheckItem>", NULL),
242 ITEM_FACTORY_ENTRY("/View/_Statusbar", NULL, statusbar_show_cb, 0, "<CheckItem>", NULL),
243 ITEM_FACTORY_ENTRY("/View/<separator>", NULL, NULL, 0, "<Separator>", NULL),
244 ITEM_FACTORY_ENTRY("/View/Packet _List", NULL, packet_list_show_cb, 0, "<CheckItem>", NULL),
245 ITEM_FACTORY_ENTRY("/View/Packet _Details", NULL, tree_view_show_cb, 0, "<CheckItem>", NULL),
246 ITEM_FACTORY_ENTRY("/View/Packet _Bytes", NULL, byte_view_show_cb, 0, "<CheckItem>", NULL),
247 ITEM_FACTORY_ENTRY("/View/<separator>", NULL, NULL, 0, "<Separator>", NULL),
248 ITEM_FACTORY_ENTRY("/View/_Time Display Format", NULL, NULL, 0, "<Branch>", NULL),
249 ITEM_FACTORY_ENTRY("/View/Time Display Format/Time of Day", NULL, timestamp_absolute_cb,
250 0, "<RadioItem>", NULL),
251 ITEM_FACTORY_ENTRY("/View/Time Display Format/Date and Time of Day", NULL, timestamp_absolute_date_cb,
252 0, "/View/Time Display Format/Time of Day", NULL),
253 ITEM_FACTORY_ENTRY("/View/Time Display Format/Seconds Since Beginning of Capture", NULL, timestamp_relative_cb,
254 0, "/View/Time Display Format/Time of Day", NULL),
255 ITEM_FACTORY_ENTRY("/View/Time Display Format/Seconds Since Previous Packet", NULL, timestamp_delta_cb,
256 0, "/View/Time Display Format/Time of Day", NULL),
257 ITEM_FACTORY_ENTRY("/View/Name Resol_ution", NULL, NULL, 0, "<Branch>", NULL),
258 ITEM_FACTORY_ENTRY("/View/Name Resolution/_Resolve Name", NULL, resolve_name_cb, 0, NULL, NULL),
259 ITEM_FACTORY_ENTRY("/View/Name Resolution/<separator>", NULL, NULL, 0, "<Separator>", NULL),
260 ITEM_FACTORY_ENTRY("/View/Name Resolution/Enable for _MAC Layer", NULL, name_resolution_mac_cb, 0, "<CheckItem>", NULL),
261 ITEM_FACTORY_ENTRY("/View/Name Resolution/Enable for _Network Layer", NULL, name_resolution_network_cb, 0, "<CheckItem>", NULL),
262 ITEM_FACTORY_ENTRY("/View/Name Resolution/Enable for _Transport Layer", NULL, name_resolution_transport_cb, 0, "<CheckItem>", NULL),
263 ITEM_FACTORY_ENTRY("/View/Colorize Packet List", NULL, colorize_cb, 0, "<CheckItem>", NULL),
265 ITEM_FACTORY_ENTRY("/View/Auto Scroll in Li_ve Capture", NULL, auto_scroll_live_cb, 0, "<CheckItem>", NULL),
267 ITEM_FACTORY_ENTRY("/View/<separator>", NULL, NULL, 0, "<Separator>", NULL),
268 ITEM_FACTORY_STOCK_ENTRY("/View/_Zoom In", "<control>plus", view_zoom_in_cb,
269 0, GTK_STOCK_ZOOM_IN),
270 ITEM_FACTORY_STOCK_ENTRY("/View/Zoom _Out", "<control>minus", view_zoom_out_cb,
271 0, GTK_STOCK_ZOOM_OUT),
272 ITEM_FACTORY_STOCK_ENTRY("/View/_Normal Size", "<control>equal", view_zoom_100_cb,
273 0, GTK_STOCK_ZOOM_100),
274 ITEM_FACTORY_STOCK_ENTRY("/View/Resize All Columns", NULL, packet_list_resize_columns_cb,
275 0, ETHEREAL_STOCK_RESIZE_COLUMNS),
276 ITEM_FACTORY_ENTRY("/View/<separator>", NULL, NULL, 0, "<Separator>", NULL),
277 ITEM_FACTORY_ENTRY("/View/E_xpand Subtrees", NULL, expand_tree_cb, 0, NULL, NULL),
278 ITEM_FACTORY_ENTRY("/View/_Expand All", NULL, expand_all_cb,
280 ITEM_FACTORY_ENTRY("/View/Collapse _All", NULL, collapse_all_cb,
282 ITEM_FACTORY_ENTRY("/View/<separator>", NULL, NULL, 0, "<Separator>", NULL),
283 ITEM_FACTORY_STOCK_ENTRY("/View/_Coloring Rules...", NULL, color_display_cb,
284 0, GTK_STOCK_SELECT_COLOR),
285 ITEM_FACTORY_ENTRY("/View/<separator>", NULL, NULL, 0, "<Separator>", NULL),
286 ITEM_FACTORY_ENTRY("/View/Show Packet in New _Window", NULL,
287 new_window_cb, 0, NULL, NULL),
288 ITEM_FACTORY_STOCK_ENTRY("/View/_Reload", "<control>R", file_reload_cmd_cb,
289 0, GTK_STOCK_REFRESH),
290 ITEM_FACTORY_ENTRY("/_Go", NULL, NULL, 0, "<Branch>", NULL),
291 ITEM_FACTORY_STOCK_ENTRY("/Go/_Back", "<alt>Left",
292 history_back_cb, 0, GTK_STOCK_GO_BACK),
293 ITEM_FACTORY_STOCK_ENTRY("/Go/_Forward", "<alt>Right",
294 history_forward_cb, 0, GTK_STOCK_GO_FORWARD),
295 ITEM_FACTORY_STOCK_ENTRY("/Go/_Go to Packet...", "<control>G",
296 goto_frame_cb, 0, GTK_STOCK_JUMP_TO),
297 ITEM_FACTORY_ENTRY("/Go/Go to _Corresponding Packet", NULL, goto_framenum_cb,
299 ITEM_FACTORY_ENTRY("/Go/<separator>", NULL, NULL, 0, "<Separator>", NULL),
300 ITEM_FACTORY_STOCK_ENTRY("/Go/F_irst Packet", NULL,
301 goto_top_frame_cb, 0, GTK_STOCK_GOTO_TOP),
302 ITEM_FACTORY_STOCK_ENTRY("/Go/_Last Packet", NULL,
303 goto_bottom_frame_cb, 0, GTK_STOCK_GOTO_BOTTOM),
305 ITEM_FACTORY_ENTRY("/_Capture", NULL, NULL, 0, "<Branch>", NULL),
306 ITEM_FACTORY_STOCK_ENTRY("/Capture/_Interfaces...", NULL,
307 capture_if_cb, 0, ETHEREAL_STOCK_CAPTURE_INTERFACES),
308 ITEM_FACTORY_STOCK_ENTRY("/Capture/_Options...", "<control>K",
309 capture_prep_cb, 0, ETHEREAL_STOCK_CAPTURE_OPTIONS),
310 ITEM_FACTORY_STOCK_ENTRY("/Capture/_Start", NULL,
311 capture_start_cb, 0, ETHEREAL_STOCK_CAPTURE_START),
312 ITEM_FACTORY_STOCK_ENTRY("/Capture/S_top", "<control>E", capture_stop_cb,
313 0, ETHEREAL_STOCK_CAPTURE_STOP),
314 ITEM_FACTORY_STOCK_ENTRY("/Capture/_Restart", NULL, capture_restart_cb,
315 0, ETHEREAL_STOCK_CAPTURE_RESTART),
316 ITEM_FACTORY_STOCK_ENTRY("/Capture/Capture _Filters...", NULL, cfilter_dialog_cb,
317 0, ETHEREAL_STOCK_CAPTURE_FILTER),
318 #endif /* HAVE_LIBPCAP */
319 ITEM_FACTORY_ENTRY("/_Analyze", NULL, NULL, 0, "<Branch>", NULL),
320 ITEM_FACTORY_STOCK_ENTRY("/Analyze/_Display Filters...", NULL, dfilter_dialog_cb,
321 0, ETHEREAL_STOCK_DISPLAY_FILTER),
322 ITEM_FACTORY_ENTRY("/Analyze/Appl_y as Filter", NULL, NULL, 0, "<Branch>", NULL),
323 ITEM_FACTORY_ENTRY("/Analyze/Apply as Filter/_Selected", NULL, match_selected_ptree_cb,
324 MATCH_SELECTED_REPLACE|MATCH_SELECTED_APPLY_NOW, NULL, NULL),
325 ITEM_FACTORY_ENTRY("/Analyze/Apply as Filter/_Not Selected", NULL, match_selected_ptree_cb,
326 MATCH_SELECTED_NOT|MATCH_SELECTED_APPLY_NOW, NULL, NULL),
327 ITEM_FACTORY_ENTRY("/Analyze/Apply as Filter/... _and Selected", NULL, match_selected_ptree_cb,
328 MATCH_SELECTED_AND|MATCH_SELECTED_APPLY_NOW, NULL, NULL),
329 ITEM_FACTORY_ENTRY("/Analyze/Apply as Filter/... _or Selected", NULL, match_selected_ptree_cb,
330 MATCH_SELECTED_OR|MATCH_SELECTED_APPLY_NOW, NULL, NULL),
331 ITEM_FACTORY_ENTRY("/Analyze/Apply as Filter/... a_nd not Selected", NULL, match_selected_ptree_cb,
332 MATCH_SELECTED_AND_NOT|MATCH_SELECTED_APPLY_NOW, NULL, NULL),
333 ITEM_FACTORY_ENTRY("/Analyze/Apply as Filter/... o_r not Selected", NULL, match_selected_ptree_cb,
334 MATCH_SELECTED_OR_NOT|MATCH_SELECTED_APPLY_NOW, NULL, NULL),
335 ITEM_FACTORY_ENTRY("/Analyze/_Prepare a Filter", NULL, NULL, 0, "<Branch>", NULL),
336 ITEM_FACTORY_ENTRY("/Analyze/Prepare a Filter/_Selected", NULL, match_selected_ptree_cb,
337 MATCH_SELECTED_REPLACE, NULL, NULL),
338 ITEM_FACTORY_ENTRY("/Analyze/Prepare a Filter/_Not Selected", NULL, match_selected_ptree_cb,
339 MATCH_SELECTED_NOT, NULL, NULL),
340 ITEM_FACTORY_ENTRY("/Analyze/Prepare a Filter/... _and Selected", NULL, match_selected_ptree_cb,
341 MATCH_SELECTED_AND, NULL, NULL),
342 ITEM_FACTORY_ENTRY("/Analyze/Prepare a Filter/... _or Selected", NULL, match_selected_ptree_cb,
343 MATCH_SELECTED_OR, NULL, NULL),
344 ITEM_FACTORY_ENTRY("/Analyze/Prepare a Filter/... a_nd not Selected", NULL, match_selected_ptree_cb,
345 MATCH_SELECTED_AND_NOT, NULL, NULL),
346 ITEM_FACTORY_ENTRY("/Analyze/Prepare a Filter/... o_r not Selected", NULL, match_selected_ptree_cb,
347 MATCH_SELECTED_OR_NOT, NULL, NULL),
348 ITEM_FACTORY_ENTRY("/Analyze/<separator>", NULL, NULL, 0, "<Separator>", NULL),
349 ITEM_FACTORY_STOCK_ENTRY("/Analyze/_Enabled Protocols...", "<shift><control>R", proto_cb, 0, ETHEREAL_STOCK_CHECKBOX),
350 ITEM_FACTORY_STOCK_ENTRY("/Analyze/Decode _As...", NULL, decode_as_cb,
351 0, ETHEREAL_STOCK_DECODE_AS),
352 ITEM_FACTORY_STOCK_ENTRY("/Analyze/_User Specified Decodes...", NULL,
353 decode_show_cb, 0, ETHEREAL_STOCK_DECODE_AS),
354 ITEM_FACTORY_ENTRY("/Analyze/<separator>", NULL, NULL, 0, "<Separator>", NULL),
355 ITEM_FACTORY_ENTRY("/Analyze/_Follow TCP Stream", NULL,
356 follow_stream_cb, 0, NULL, NULL),
357 ITEM_FACTORY_ENTRY("/_Statistics", NULL, NULL, 0, "<Branch>", NULL),
358 ITEM_FACTORY_STOCK_ENTRY("/Statistics/_Summary", NULL, summary_open_cb, 0, GTK_STOCK_PROPERTIES),
359 ITEM_FACTORY_ENTRY("/Statistics/_Protocol Hierarchy", NULL,
360 proto_hier_stats_cb, 0, NULL, NULL),
361 ITEM_FACTORY_STOCK_ENTRY("/Statistics/Conversations", NULL,
362 init_conversation_notebook_cb, 0, ETHEREAL_STOCK_CONVERSATIONS),
363 ITEM_FACTORY_STOCK_ENTRY("/Statistics/Endpoints", NULL,
364 init_hostlist_notebook_cb, 0, ETHEREAL_STOCK_ENDPOINTS),
365 ITEM_FACTORY_ENTRY("/_Help", NULL, NULL, 0, "<Branch>", NULL),
366 ITEM_FACTORY_STOCK_ENTRY("/Help/_Contents", "F1", topic_menu_cb, HELP_CONTENT, GTK_STOCK_HELP),
367 ITEM_FACTORY_ENTRY("/Help/_Supported Protocols", NULL, supported_cb, 0, NULL, NULL),
368 #if (GLIB_MAJOR_VERSION >= 2)
369 #ifdef ETHEREAL_EUG_DIR
370 ITEM_FACTORY_ENTRY("/Help/User's Guide", NULL, url_page_menu_cb, HELP_CONTENT, NULL, NULL),
372 ITEM_FACTORY_ENTRY("/Help/Manual Pages", NULL, NULL, 0, "<Branch>", NULL),
373 ITEM_FACTORY_ENTRY("/Help/Manual Pages/Ethereal", NULL, topic_menu_cb, LOCALPAGE_MAN_ETHEREAL, NULL, NULL),
374 ITEM_FACTORY_ENTRY("/Help/Manual Pages/Ethereal Filter", NULL, topic_menu_cb, LOCALPAGE_MAN_ETHEREAL_FILTER, NULL, NULL),
375 ITEM_FACTORY_ENTRY("/Help/Manual Pages/<separator>", NULL, NULL, 0, "<Separator>", NULL),
376 ITEM_FACTORY_ENTRY("/Help/Manual Pages/Tethereal", NULL, topic_menu_cb, LOCALPAGE_MAN_TETHEREAL, NULL, NULL),
377 ITEM_FACTORY_ENTRY("/Help/Manual Pages/Mergecap", NULL, topic_menu_cb, LOCALPAGE_MAN_MERGECAP, NULL, NULL),
378 ITEM_FACTORY_ENTRY("/Help/Manual Pages/Editcap", NULL, topic_menu_cb, LOCALPAGE_MAN_EDITCAP, NULL, NULL),
379 ITEM_FACTORY_ENTRY("/Help/Manual Pages/Text2pcap", NULL, topic_menu_cb, LOCALPAGE_MAN_TEXT2PCAP, NULL, NULL),
380 ITEM_FACTORY_ENTRY("/Help/Ethereal Online", NULL, NULL, 0, "<Branch>", NULL),
381 ITEM_FACTORY_STOCK_ENTRY("/Help/Ethereal Online/Home Page", NULL, topic_menu_cb, ONLINEPAGE_HOME, GTK_STOCK_HOME),
382 ITEM_FACTORY_STOCK_ENTRY("/Help/Ethereal Online/Wiki", NULL, topic_menu_cb, ONLINEPAGE_WIKI, ETHEREAL_STOCK_WIKI),
383 ITEM_FACTORY_STOCK_ENTRY("/Help/Ethereal Online/User's Guide", NULL, topic_menu_cb, ONLINEPAGE_USERGUIDE, ETHEREAL_STOCK_WEB_SUPPORT),
384 ITEM_FACTORY_ENTRY("/Help/Ethereal Online/FAQ's", NULL, topic_menu_cb, ONLINEPAGE_FAQ, NULL, NULL),
385 ITEM_FACTORY_ENTRY("/Help/Ethereal Online/Downloads", NULL, topic_menu_cb, ONLINEPAGE_DOWNLOAD, NULL, NULL),
386 ITEM_FACTORY_ENTRY("/Help/Ethereal Online/Example Files", NULL, topic_menu_cb, ONLINEPAGE_SAMPLE_FILES, NULL, NULL),
388 ITEM_FACTORY_ENTRY("/Help/<separator>", NULL, NULL, 0, "<Separator>", NULL),
389 ITEM_FACTORY_STOCK_ENTRY("/Help/_About Ethereal", NULL, about_ethereal_cb,
390 0, ETHEREAL_STOCK_ABOUT)
394 /* calculate the number of menu_items */
395 static int nmenu_items = sizeof(menu_items) / sizeof(menu_items[0]);
397 /* packet list popup */
398 static GtkItemFactoryEntry packet_list_menu_items[] =
400 ITEM_FACTORY_ENTRY("/Mark Packet (toggle)", NULL, mark_frame_cb, 0, NULL, NULL),
401 ITEM_FACTORY_ENTRY("/Time Reference", NULL, NULL, 0, "<Branch>", NULL),
402 ITEM_FACTORY_STOCK_ENTRY("/Time Reference/Set Time Reference (toggle)", NULL, reftime_frame_cb, REFTIME_TOGGLE, ETHEREAL_STOCK_TIME),
403 ITEM_FACTORY_ENTRY("/Time Reference/Find Next", NULL, reftime_frame_cb, REFTIME_FIND_NEXT, NULL, NULL),
404 ITEM_FACTORY_ENTRY("/Time Reference/Find Previous", NULL, reftime_frame_cb, REFTIME_FIND_PREV, NULL, NULL),
406 ITEM_FACTORY_ENTRY("/<separator>", NULL, NULL, 0, "<Separator>", NULL),
408 ITEM_FACTORY_ENTRY("/Apply as Filter", NULL, NULL, 0, "<Branch>", NULL),
409 ITEM_FACTORY_ENTRY("/Apply as Filter/_Selected", NULL, match_selected_plist_cb,
410 MATCH_SELECTED_REPLACE|MATCH_SELECTED_APPLY_NOW, NULL, NULL),
411 ITEM_FACTORY_ENTRY("/Apply as Filter/_Not Selected", NULL, match_selected_plist_cb,
412 MATCH_SELECTED_NOT|MATCH_SELECTED_APPLY_NOW, NULL, NULL),
413 ITEM_FACTORY_ENTRY("/Apply as Filter/... _and Selected", NULL, match_selected_plist_cb,
414 MATCH_SELECTED_AND|MATCH_SELECTED_APPLY_NOW, NULL, NULL),
415 ITEM_FACTORY_ENTRY("/Apply as Filter/... _or Selected", NULL, match_selected_plist_cb,
416 MATCH_SELECTED_OR|MATCH_SELECTED_APPLY_NOW, NULL, NULL),
417 ITEM_FACTORY_ENTRY("/Apply as Filter/... a_nd not Selected", NULL, match_selected_plist_cb,
418 MATCH_SELECTED_AND_NOT|MATCH_SELECTED_APPLY_NOW, NULL, NULL),
419 ITEM_FACTORY_ENTRY("/Apply as Filter/... o_r not Selected", NULL, match_selected_plist_cb,
420 MATCH_SELECTED_OR_NOT|MATCH_SELECTED_APPLY_NOW, NULL, NULL),
422 ITEM_FACTORY_ENTRY("/Prepare a Filter", NULL, NULL, 0, "<Branch>", NULL),
423 ITEM_FACTORY_ENTRY("/Prepare a Filter/_Selected", NULL, match_selected_plist_cb,
424 MATCH_SELECTED_REPLACE, NULL, NULL),
425 ITEM_FACTORY_ENTRY("/Prepare a Filter/_Not Selected", NULL, match_selected_plist_cb,
426 MATCH_SELECTED_NOT, NULL, NULL),
427 ITEM_FACTORY_ENTRY("/Prepare a Filter/... _and Selected", NULL, match_selected_plist_cb,
428 MATCH_SELECTED_AND, NULL, NULL),
429 ITEM_FACTORY_ENTRY("/Prepare a Filter/... _or Selected", NULL, match_selected_plist_cb,
430 MATCH_SELECTED_OR, NULL, NULL),
431 ITEM_FACTORY_ENTRY("/Prepare a Filter/... a_nd not Selected", NULL, match_selected_plist_cb,
432 MATCH_SELECTED_AND_NOT, NULL, NULL),
433 ITEM_FACTORY_ENTRY("/Prepare a Filter/... o_r not Selected", NULL, match_selected_plist_cb,
434 MATCH_SELECTED_OR_NOT, NULL, NULL),
436 ITEM_FACTORY_ENTRY("/Follow TCP Stream", NULL, follow_stream_cb,
439 ITEM_FACTORY_ENTRY("/<separator>", NULL, NULL, 0, "<Separator>", NULL),
441 ITEM_FACTORY_STOCK_ENTRY("/Decode As...", NULL, decode_as_cb, 0, ETHEREAL_STOCK_DECODE_AS),
442 ITEM_FACTORY_STOCK_ENTRY("/Print...", NULL, file_print_selected_cmd_cb, 0, GTK_STOCK_PRINT),
443 ITEM_FACTORY_ENTRY("/Show Packet in New Window", NULL, new_window_cb,
447 static GtkItemFactoryEntry tree_view_menu_items[] =
449 ITEM_FACTORY_ENTRY("/Expand Subtrees", NULL, expand_tree_cb, 0, NULL, NULL),
450 ITEM_FACTORY_ENTRY("/Expand All", NULL, expand_all_cb, 0, NULL, NULL),
451 ITEM_FACTORY_ENTRY("/Collapse All", NULL, collapse_all_cb, 0, NULL, NULL),
453 ITEM_FACTORY_ENTRY("/<separator>", NULL, NULL, 0, "<Separator>", NULL),
455 ITEM_FACTORY_ENTRY("/Apply as Filter", NULL, NULL, 0, "<Branch>", NULL),
456 ITEM_FACTORY_ENTRY("/Apply as Filter/_Selected", NULL, match_selected_ptree_cb,
457 MATCH_SELECTED_REPLACE|MATCH_SELECTED_APPLY_NOW, NULL, NULL),
458 ITEM_FACTORY_ENTRY("/Apply as Filter/_Not Selected", NULL, match_selected_ptree_cb,
459 MATCH_SELECTED_NOT|MATCH_SELECTED_APPLY_NOW, NULL, NULL),
460 ITEM_FACTORY_ENTRY("/Apply as Filter/... _and Selected", NULL, match_selected_ptree_cb,
461 MATCH_SELECTED_AND|MATCH_SELECTED_APPLY_NOW, NULL, NULL),
462 ITEM_FACTORY_ENTRY("/Apply as Filter/... _or Selected", NULL, match_selected_ptree_cb,
463 MATCH_SELECTED_OR|MATCH_SELECTED_APPLY_NOW, NULL, NULL),
464 ITEM_FACTORY_ENTRY("/Apply as Filter/... a_nd not Selected", NULL, match_selected_ptree_cb,
465 MATCH_SELECTED_AND_NOT|MATCH_SELECTED_APPLY_NOW, NULL, NULL),
466 ITEM_FACTORY_ENTRY("/Apply as Filter/... o_r not Selected", NULL, match_selected_ptree_cb,
467 MATCH_SELECTED_OR_NOT|MATCH_SELECTED_APPLY_NOW, NULL, NULL),
469 ITEM_FACTORY_ENTRY("/Prepare a Filter", NULL, NULL, 0, "<Branch>", NULL),
470 ITEM_FACTORY_ENTRY("/Prepare a Filter/_Selected", NULL, match_selected_ptree_cb,
471 MATCH_SELECTED_REPLACE, NULL, NULL),
472 ITEM_FACTORY_ENTRY("/Prepare a Filter/_Not Selected", NULL, match_selected_ptree_cb,
473 MATCH_SELECTED_NOT, NULL, NULL),
474 ITEM_FACTORY_ENTRY("/Prepare a Filter/... _and Selected", NULL, match_selected_ptree_cb,
475 MATCH_SELECTED_AND, NULL, NULL),
476 ITEM_FACTORY_ENTRY("/Prepare a Filter/... _or Selected", NULL, match_selected_ptree_cb,
477 MATCH_SELECTED_OR, NULL, NULL),
478 ITEM_FACTORY_ENTRY("/Prepare a Filter/... a_nd not Selected", NULL, match_selected_ptree_cb,
479 MATCH_SELECTED_AND_NOT, NULL, NULL),
480 ITEM_FACTORY_ENTRY("/Prepare a Filter/... o_r not Selected", NULL, match_selected_ptree_cb,
481 MATCH_SELECTED_OR_NOT, NULL, NULL),
483 ITEM_FACTORY_ENTRY("/Follow TCP Stream", NULL, follow_stream_cb,
486 ITEM_FACTORY_ENTRY("/<separator>", NULL, NULL, 0, "<Separator>", NULL),
488 ITEM_FACTORY_STOCK_ENTRY("/Wiki Protocol Page", NULL, selected_ptree_info_cb,
489 0, ETHEREAL_STOCK_WIKI),
490 ITEM_FACTORY_STOCK_ENTRY("/Filter Field Reference", NULL, selected_ptree_ref_cb,
491 0, ETHEREAL_STOCK_INTERNET),
492 ITEM_FACTORY_ENTRY("/Protocol Preferences...", NULL, properties_cb,
494 ITEM_FACTORY_ENTRY("/<separator>", NULL, NULL, 0, "<Separator>", NULL),
495 ITEM_FACTORY_STOCK_ENTRY("/Decode As...", NULL, decode_as_cb, 0, ETHEREAL_STOCK_DECODE_AS),
496 ITEM_FACTORY_ENTRY("/_Resolve Name", NULL, resolve_name_cb, 0, NULL, NULL),
497 ITEM_FACTORY_ENTRY("/_Go to Corresponding Packet", NULL, goto_framenum_cb, 0, NULL, NULL),
500 static GtkItemFactoryEntry hexdump_menu_items[] =
502 ITEM_FACTORY_ENTRY("/Copy", NULL, copy_hex_cb,
504 ITEM_FACTORY_ENTRY("/Export Selected Packet Bytes...", NULL, savehex_cb,
508 static int initialize = TRUE;
509 static GtkItemFactory *main_menu_factory = NULL;
510 static GtkItemFactory *packet_list_menu_factory = NULL;
511 static GtkItemFactory *tree_view_menu_factory = NULL;
512 static GtkItemFactory *hexdump_menu_factory = NULL;
514 static GSList *popup_menu_list = NULL;
516 static GtkAccelGroup *grp;
519 main_menu_new(GtkAccelGroup ** table) {
522 grp = gtk_accel_group_new();
527 menubar = main_menu_factory->widget;
541 packet_list_menu_factory = gtk_item_factory_new(GTK_TYPE_MENU, "<main>", NULL);
542 popup_menu_object = gtk_menu_new();
543 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);
544 OBJECT_SET_DATA(popup_menu_object, PM_PACKET_LIST_KEY,
545 packet_list_menu_factory->widget);
546 popup_menu_list = g_slist_append((GSList *)popup_menu_list, packet_list_menu_factory);
548 tree_view_menu_factory = gtk_item_factory_new(GTK_TYPE_MENU, "<main>", NULL);
549 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);
550 OBJECT_SET_DATA(popup_menu_object, PM_TREE_VIEW_KEY,
551 tree_view_menu_factory->widget);
552 popup_menu_list = g_slist_append((GSList *)popup_menu_list, tree_view_menu_factory);
554 hexdump_menu_factory = gtk_item_factory_new(GTK_TYPE_MENU, "<main>", NULL);
555 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);
556 OBJECT_SET_DATA(popup_menu_object, PM_HEXDUMP_KEY,
557 hexdump_menu_factory->widget);
558 popup_menu_list = g_slist_append((GSList *)popup_menu_list, hexdump_menu_factory);
561 main_menu_factory = gtk_item_factory_new(GTK_TYPE_MENU_BAR, "<main>", grp);
562 gtk_item_factory_create_items_ac(main_menu_factory, nmenu_items, menu_items, NULL, 2);
564 merge_all_tap_menus(tap_menu_tree_root);
566 /* Initialize enabled/disabled state of menu items */
567 set_menus_for_unsaved_capture_file(FALSE);
568 set_menus_for_capture_file(FALSE);
570 /* Un-#if this when we actually implement Cut/Copy/Paste.
571 Then make sure you enable them when they can be done. */
572 set_menu_sensitivity(main_menu_factory, "/Edit/Cut", FALSE);
573 set_menu_sensitivity(main_menu_factory, "/Edit/Copy", FALSE);
574 set_menu_sensitivity(main_menu_factory, "/Edit/Paste", FALSE);
577 set_menus_for_captured_packets(FALSE);
578 set_menus_for_selected_packet(&cfile);
579 set_menus_for_selected_tree_row(&cfile);
580 set_menus_for_capture_in_progress(FALSE);
582 /* init with an empty recent files list */
583 clear_menu_recent_capture_file_cmd_cb(NULL, NULL);
588 static gint tap_menu_item_add_compare(gconstpointer a, gconstpointer b)
591 ((const menu_item_t *) a)->name,
592 ((const menu_item_t *) b)->name);
596 /* add a menuitem below the current node */
597 static GList * tap_menu_item_add(
600 GtkItemFactoryCallback callback,
601 gboolean (*selected_packet_enabled)(frame_data *, epan_dissect_t *),
602 gboolean (*selected_tree_row_enabled)(field_info *),
603 gpointer callback_data,
610 child = g_malloc(sizeof (menu_item_t));
611 child->group = group;
613 child->callback = callback;
614 child->selected_packet_enabled = selected_packet_enabled;
615 child->selected_tree_row_enabled = selected_tree_row_enabled;
616 child->callback_data = callback_data;
617 child->enabled = FALSE;
618 child->children = NULL;
620 /* insert the new child node into the parent */
621 curr = curnode->data;
622 curr->children = g_list_insert_sorted(curr->children, child, tap_menu_item_add_compare);
624 /* return the new node */
625 /* XXX: improve this */
626 return g_list_find(curr->children, child);
630 * Add a new menu item for a tap.
631 * This must be called after we've created the main menu, so it can't
632 * be called from the routine that registers taps - we have to introduce
633 * another per-tap registration routine.
635 * "callback" gets called when the menu item is selected; it should do
636 * the work of creating the tap window.
638 * "selected_packet_enabled" gets called by "set_menus_for_selected_packet()";
639 * it's passed a Boolean that's TRUE if a packet is selected and FALSE
640 * otherwise, and should return TRUE if the tap will work now (which
641 * might depend on whether a packet is selected and, if one is, on the
642 * packet) and FALSE if not.
644 * "selected_tree_row_enabled" gets called by
645 * "set_menus_for_selected_tree_row()"; it's passed a Boolean that's TRUE if
646 * a protocol tree row is selected and FALSE otherwise, and should return
647 * TRUE if the tap will work now (which might depend on whether a tree row
648 * is selected and, if one is, on the tree row) and FALSE if not.
651 register_tap_menu_item(
653 REGISTER_TAP_GROUP_E group,
654 GtkItemFactoryCallback callback,
655 gboolean (*selected_packet_enabled)(frame_data *, epan_dissect_t *),
656 gboolean (*selected_tree_row_enabled)(field_info *),
657 gpointer callback_data)
659 /*static const char toolspath[] = "/Statistics/";*/
669 * The menu path must be relative.
671 g_assert(*name != '/');
674 case(REGISTER_TAP_GROUP_GENERIC): toolspath = "/Statistics/"; break;
675 case(REGISTER_TAP_GROUP_CONVERSATION_LIST): toolspath = "/Statistics/_Conversation List/"; break;
676 case(REGISTER_TAP_GROUP_ENDPOINT_LIST): toolspath = "/Statistics/_Endpoint List/"; break;
677 case(REGISTER_TAP_GROUP_RESPONSE_TIME): toolspath = "/Statistics/Service _Response Time/"; break;
678 case(REGISTER_TAP_GROUP_TELEPHONY): toolspath = "/Statistics/"; break;
679 case(REGISTER_TAP_GROUP_NONE): toolspath = "/Statistics/"; break;
685 /* add the (empty) root node, if not already done */
686 if(tap_menu_tree_root == NULL) {
687 child = g_malloc0(sizeof (menu_item_t));
688 tap_menu_tree_root = g_list_append(NULL, child);
692 * Create any submenus required.
694 curnode = tap_menu_tree_root;
696 while ((p = strchr(p, '/')) != NULL) {
698 * OK, everything between "name" and "p" is
699 * a menu relative subtree into which the menu item
702 * Construct the absolute path name of that subtree.
704 menupathlen = strlen(toolspath) + 1 + (p - name);
705 menupath = g_malloc(menupathlen);
706 strcpy(menupath, toolspath);
707 strncat(menupath, name, p - name);
710 * Does there exist an entry with that path at this
711 * level of the Analyze menu tree?
713 child = curnode->data;
714 for (childnode = child->children; childnode != NULL; childnode = childnode->next) {
715 child = childnode->data;
716 if (strcmp(child->name, menupath) == 0)
719 if (childnode == NULL) {
721 * No. Create such an item as a subtree, and
722 * add it to the Tools menu tree.
724 childnode = tap_menu_item_add(
725 menupath, group, NULL, NULL ,NULL, NULL, curnode);
728 * Yes. We don't need this "menupath" any longer.
735 * Skip over the '/' we found.
741 * Construct the main menu path for the menu item.
743 menupathlen = strlen(toolspath) + 1 + strlen(name);
744 menupath = g_malloc(menupathlen);
745 strcpy(menupath, toolspath);
746 strcat(menupath, name);
749 * Construct an item factory entry for the item, and add it to
753 menupath, group, callback,
754 selected_packet_enabled, selected_tree_row_enabled,
755 callback_data, curnode);
759 static guint merge_tap_menus_layered(GList *node, gint group) {
760 GtkItemFactoryEntry *entry;
763 menu_item_t *node_data = node->data;
766 * Is this a leaf node or an interior node?
768 if (node_data->children == NULL) {
774 * The root node doesn't correspond to a menu tree item; it
775 * has a null name pointer.
777 if (node_data->name != NULL && group == node_data->group) {
778 entry = g_malloc0(sizeof (GtkItemFactoryEntry));
779 entry->path = node_data->name;
780 entry->callback = node_data->callback;
781 #if GTK_MAJOR_VERSION >= 2
783 case(REGISTER_TAP_GROUP_NONE):
785 case(REGISTER_TAP_GROUP_GENERIC):
787 case(REGISTER_TAP_GROUP_CONVERSATION_LIST):
788 entry->item_type = "<StockItem>";
789 entry->extra_data = ETHEREAL_STOCK_CONVERSATIONS;
791 case(REGISTER_TAP_GROUP_ENDPOINT_LIST):
792 entry->item_type = "<StockItem>";
793 entry->extra_data = ETHEREAL_STOCK_ENDPOINTS;
795 case(REGISTER_TAP_GROUP_RESPONSE_TIME):
796 entry->item_type = "<StockItem>";
797 entry->extra_data = ETHEREAL_STOCK_TIME;
799 case(REGISTER_TAP_GROUP_TELEPHONY):
800 entry->item_type = "<StockItem>";
801 entry->extra_data = ETHEREAL_STOCK_TELEPHONY;
804 g_assert_not_reached();
807 gtk_item_factory_create_item(main_menu_factory, entry, node_data->callback_data, 2);
808 set_menu_sensitivity(main_menu_factory, node_data->name, FALSE); /* no capture file yet */
813 * It's an interior node; call
814 * "merge_tap_menus_layered()" on all its children
818 * The root node doesn't correspond to a menu tree item; it
819 * has a null name pointer.
821 if (node_data->name != NULL && group == node_data->group) {
822 entry = g_malloc0(sizeof (GtkItemFactoryEntry));
823 entry->path = node_data->name;
824 entry->item_type = "<Branch>";
825 gtk_item_factory_create_item(main_menu_factory, entry,
827 set_menu_sensitivity(main_menu_factory, node_data->name,
828 FALSE); /* no children yet */
832 for (child = node_data->children; child != NULL; child =
834 added += merge_tap_menus_layered(child, group);
842 void merge_all_tap_menus(GList *node) {
843 GtkItemFactoryEntry *entry;
845 entry = g_malloc0(sizeof (GtkItemFactoryEntry));
846 entry->item_type = "<Separator>";
847 entry->path = "/Statistics/";
850 * merge only the menu items of the specific group,
851 * and then append a seperator
853 if (merge_tap_menus_layered(node, REGISTER_TAP_GROUP_GENERIC)) {
854 gtk_item_factory_create_item(main_menu_factory, entry, NULL, 2);
856 if (merge_tap_menus_layered(node, REGISTER_TAP_GROUP_CONVERSATION_LIST)) {
857 /*gtk_item_factory_create_item(main_menu_factory, entry, NULL, 2);*/
859 if (merge_tap_menus_layered(node, REGISTER_TAP_GROUP_ENDPOINT_LIST)) {
860 /*gtk_item_factory_create_item(main_menu_factory, entry, NULL, 2);*/
862 if (merge_tap_menus_layered(node, REGISTER_TAP_GROUP_RESPONSE_TIME)) {
863 gtk_item_factory_create_item(main_menu_factory, entry, NULL, 2);
865 if (merge_tap_menus_layered(node, REGISTER_TAP_GROUP_TELEPHONY)) {
866 gtk_item_factory_create_item(main_menu_factory, entry, NULL, 2);
868 if (merge_tap_menus_layered(node, REGISTER_TAP_GROUP_NONE)) {
869 /*gtk_item_factory_create_item(main_menu_factory, entry, NULL, 2);*/
876 * Enable/disable menu sensitivity.
879 set_menu_sensitivity(GtkItemFactory *ifactory, const gchar *path, gint val)
882 GtkWidget *menu_item;
887 /* the underscore character regularly confuses things, as it will prevent finding
888 * the menu_item, so it has to be removed first */
889 dup = g_strdup(path);
900 if (ifactory == NULL) {
902 * Do it for all pop-up menus.
904 for (menu_list = popup_menu_list; menu_list != NULL;
905 menu_list = g_slist_next(menu_list))
906 set_menu_sensitivity(menu_list->data, dup, val);
909 * Do it for that particular menu.
911 if ((menu_item = gtk_item_factory_get_widget(ifactory, dup)) != NULL) {
912 if (GTK_IS_MENU(menu_item)) {
914 * "dup" refers to a submenu; "gtk_item_factory_get_widget()"
915 * gets the menu, not the item that, when selected, pops up
918 * We have to change the latter item's sensitivity, so that
919 * it shows up normally if sensitive and grayed-out if
922 menu_item = gtk_menu_get_attach_widget(GTK_MENU(menu_item));
924 gtk_widget_set_sensitive(menu_item, val);
926 /* be sure this menu item *is* existing */
927 g_assert_not_reached();
935 set_menu_object_data_meat(GtkItemFactory *ifactory, gchar *path, gchar *key, gpointer data)
937 GtkWidget *menu = NULL;
939 if ((menu = gtk_item_factory_get_widget(ifactory, path)) != NULL)
940 OBJECT_SET_DATA(menu, key, data);
944 set_menu_object_data (gchar *path, gchar *key, gpointer data) {
945 GSList *menu_list = popup_menu_list;
946 gchar *shortpath = strrchr(path, '/');
948 set_menu_object_data_meat(main_menu_factory, path, key, data);
949 while (menu_list != NULL) {
950 set_menu_object_data_meat(menu_list->data, shortpath, key, data);
951 menu_list = g_slist_next(menu_list);
956 /* Recently used capture files submenu:
957 * Submenu containing the recently used capture files.
958 * The capture filenames are always kept with the absolute path, to be independant
959 * of the current path.
960 * They are only stored inside the labels of the submenu (no separate list). */
962 #define MENU_RECENT_FILES_PATH "/File/Open Recent"
963 #define MENU_RECENT_FILES_KEY "Recent File Name"
966 update_menu_recent_capture_file1(GtkWidget *widget, gpointer cnt) {
967 gchar *widget_cf_name;
969 widget_cf_name = OBJECT_GET_DATA(widget, MENU_RECENT_FILES_KEY);
971 /* if this menu item is a file, count it */
972 if (widget_cf_name) {
978 /* update the menu */
980 update_menu_recent_capture_file(GtkWidget *submenu_recent_files) {
983 gtk_container_foreach(GTK_CONTAINER(submenu_recent_files),
984 update_menu_recent_capture_file1, &cnt);
986 /* make parent menu item sensitive only, if we have any valid files in the list */
987 set_menu_sensitivity(main_menu_factory, MENU_RECENT_FILES_PATH, cnt);
991 /* remove the capture filename from the "Recent Files" menu */
993 remove_menu_recent_capture_file(GtkWidget *widget, gpointer unused _U_) {
994 GtkWidget *submenu_recent_files;
995 gchar *widget_cf_name;
998 widget_cf_name = OBJECT_GET_DATA(widget, MENU_RECENT_FILES_KEY);
999 g_free(widget_cf_name);
1001 /* get the submenu container item */
1002 submenu_recent_files = gtk_item_factory_get_widget(main_menu_factory, MENU_RECENT_FILES_PATH);
1004 /* XXX: is this all we need to do, to free the menu item and its label?
1005 The reference count of widget will go to 0, so it'll be freed;
1006 will that free the label? */
1007 gtk_container_remove(GTK_CONTAINER(submenu_recent_files), widget);
1011 /* callback, if the user pushed the <Clear File List> item */
1013 clear_menu_recent_capture_file_cmd_cb(GtkWidget *w _U_, gpointer unused _U_) {
1014 GtkWidget *submenu_recent_files;
1017 submenu_recent_files = gtk_item_factory_get_widget(main_menu_factory, MENU_RECENT_FILES_PATH);
1019 gtk_container_foreach(GTK_CONTAINER(submenu_recent_files),
1020 remove_menu_recent_capture_file, NULL);
1022 update_menu_recent_capture_file(submenu_recent_files);
1026 /* callback, if the user pushed a recent file submenu item */
1028 menu_open_recent_file_cmd(GtkWidget *w)
1030 GtkWidget *submenu_recent_files;
1031 GtkWidget *menu_item_child;
1035 submenu_recent_files = gtk_item_factory_get_widget(main_menu_factory, MENU_RECENT_FILES_PATH);
1037 /* get capture filename from the menu item label */
1038 menu_item_child = (GTK_BIN(w))->child;
1039 gtk_label_get(GTK_LABEL(menu_item_child), &cf_name);
1041 /* open and read the capture file (this will close an existing file) */
1042 if (cf_open(&cfile, cf_name, FALSE, &err) == CF_OK) {
1045 /* the capture file isn't existing any longer, remove menu item */
1046 /* XXX: ask user to remove item, it's maybe only a temporary problem */
1047 remove_menu_recent_capture_file(w, NULL);
1050 update_menu_recent_capture_file(submenu_recent_files);
1053 static void menu_open_recent_file_answered_cb(gpointer dialog _U_, gint btn, gpointer data _U_)
1057 /* save file first */
1058 file_save_as_cmd(after_save_open_recent_file, data);
1062 menu_open_recent_file_cmd(data);
1064 case(ESD_BTN_CANCEL):
1067 g_assert_not_reached();
1072 menu_open_recent_file_cmd_cb(GtkWidget *widget, gpointer data _U_) {
1076 if((cfile.state != FILE_CLOSED) && !cfile.user_saved && prefs.gui_ask_unsaved) {
1077 /* user didn't saved his current file, ask him */
1078 dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_YES_NO_CANCEL,
1079 PRIMARY_TEXT_START "Save capture file before opening a new one?" PRIMARY_TEXT_END "\n\n"
1080 "If you open a new capture file without saving, your current capture data will be discarded.");
1081 simple_dialog_set_cb(dialog, menu_open_recent_file_answered_cb, widget);
1083 /* unchanged file */
1084 menu_open_recent_file_cmd(widget);
1088 /* add the capture filename (with an absolute path) to the "Recent Files" menu */
1090 add_menu_recent_capture_file_absolute(gchar *cf_name) {
1091 GtkWidget *submenu_recent_files;
1092 GList *menu_item_list;
1094 gchar *widget_cf_name;
1095 gchar *normalized_cf_name;
1096 GtkWidget *menu_item;
1101 normalized_cf_name = g_strdup(cf_name);
1103 /* replace all slashes by backslashes */
1104 g_strdelimit(normalized_cf_name, "/", '\\');
1107 /* get the submenu container item */
1108 submenu_recent_files = gtk_item_factory_get_widget(main_menu_factory, MENU_RECENT_FILES_PATH);
1110 /* convert container to a GList */
1111 menu_item_list = gtk_container_children(GTK_CONTAINER(submenu_recent_files));
1113 /* iterate through list items of menu_item_list,
1114 * removing special items, a maybe duplicate entry and every item above count_max */
1116 for (li = g_list_first(menu_item_list); li; li = li->next, cnt++) {
1117 /* get capture filename */
1118 menu_item = GTK_WIDGET(li->data);
1119 widget_cf_name = OBJECT_GET_DATA(menu_item, MENU_RECENT_FILES_KEY);
1121 /* if this element string is one of our special items (seperator, ...) or
1122 * already in the list or
1123 * this element is above maximum count (too old), remove it */
1124 if (!widget_cf_name ||
1126 /* do a case insensitive compare on win32 */
1127 #if GLIB_MAJOR_VERSION < 2
1128 g_strncasecmp(widget_cf_name, normalized_cf_name, 1000) == 0 ||
1130 g_ascii_strncasecmp(widget_cf_name, normalized_cf_name, 1000) == 0 ||
1133 /* do a case sensitive compare on unix */
1134 strncmp(widget_cf_name, normalized_cf_name, 1000) == 0 ||
1136 cnt >= prefs.gui_recent_files_count_max) {
1137 remove_menu_recent_capture_file(li->data, NULL);
1142 g_list_free(menu_item_list);
1144 /* add new item at latest position */
1145 menu_item = gtk_menu_item_new_with_label(normalized_cf_name);
1146 OBJECT_SET_DATA(menu_item, MENU_RECENT_FILES_KEY, normalized_cf_name);
1147 gtk_menu_prepend (GTK_MENU(submenu_recent_files), menu_item);
1148 SIGNAL_CONNECT_OBJECT(GTK_OBJECT(menu_item), "activate",
1149 menu_open_recent_file_cmd_cb, (GtkObject *) menu_item);
1150 gtk_widget_show (menu_item);
1152 /* add seperator at last position */
1153 menu_item = gtk_menu_item_new();
1154 gtk_menu_append (GTK_MENU(submenu_recent_files), menu_item);
1155 gtk_widget_show (menu_item);
1157 /* add new "clear list" item at last position */
1158 #if GTK_MAJOR_VERSION < 2
1159 menu_item = gtk_menu_item_new_with_label("<Clear File List>");
1161 menu_item = gtk_image_menu_item_new_from_stock(GTK_STOCK_CLEAR, NULL);
1163 gtk_menu_append (GTK_MENU(submenu_recent_files), menu_item);
1164 SIGNAL_CONNECT_OBJECT(GTK_OBJECT(menu_item), "activate",
1165 clear_menu_recent_capture_file_cmd_cb, (GtkObject *) menu_item);
1166 gtk_widget_show (menu_item);
1168 update_menu_recent_capture_file(submenu_recent_files);
1172 /* add the capture filename to the "Recent Files" menu */
1173 /* (will change nothing, if this filename is already in the menu) */
1175 add_menu_recent_capture_file(gchar *cf_name) {
1180 /* if this filename is an absolute path, we can use it directly */
1181 if (g_path_is_absolute(cf_name)) {
1182 add_menu_recent_capture_file_absolute(cf_name);
1186 /* this filename is not an absolute path, prepend the current dir */
1187 curr = g_get_current_dir();
1188 absolute = g_strdup_printf("%s%s%s", curr, G_DIR_SEPARATOR_S, cf_name);
1189 add_menu_recent_capture_file_absolute(absolute);
1195 /* write all capture filenames of the menu to the user's recent file */
1197 menu_recent_file_write_all(FILE *rf) {
1198 GtkWidget *submenu_recent_files;
1204 submenu_recent_files = gtk_item_factory_get_widget(main_menu_factory, MENU_RECENT_FILES_PATH);
1206 /* we have to iterate backwards through the children's list,
1207 * so we get the latest item last in the file.
1208 * (don't use gtk_container_foreach() here, it will return the wrong iteration order) */
1209 children = gtk_container_children(GTK_CONTAINER(submenu_recent_files));
1210 child = g_list_last(children);
1211 while(child != NULL) {
1212 /* get capture filename from the menu item label */
1213 cf_name = OBJECT_GET_DATA(child->data, MENU_RECENT_FILES_KEY);
1215 fprintf (rf, RECENT_KEY_CAPTURE_FILE ": %s\n", cf_name);
1218 child = g_list_previous(child);
1221 g_list_free(children);
1226 main_toolbar_show_cb(GtkWidget *w _U_, gpointer d _U_)
1229 /* save current setting in recent */
1230 recent.main_toolbar_show = GTK_CHECK_MENU_ITEM(w)->active;
1232 main_widgets_show_or_hide();
1237 filter_toolbar_show_cb(GtkWidget *w _U_, gpointer d _U_)
1240 /* save current setting in recent */
1241 recent.filter_toolbar_show = GTK_CHECK_MENU_ITEM(w)->active;
1243 main_widgets_show_or_hide();
1248 packet_list_show_cb(GtkWidget *w _U_, gpointer d _U_)
1251 /* save current setting in recent */
1252 recent.packet_list_show = GTK_CHECK_MENU_ITEM(w)->active;
1254 main_widgets_show_or_hide();
1259 tree_view_show_cb(GtkWidget *w _U_, gpointer d _U_)
1262 /* save current setting in recent */
1263 recent.tree_view_show = GTK_CHECK_MENU_ITEM(w)->active;
1265 main_widgets_show_or_hide();
1270 byte_view_show_cb(GtkWidget *w _U_, gpointer d _U_)
1273 /* save current setting in recent */
1274 recent.byte_view_show = GTK_CHECK_MENU_ITEM(w)->active;
1276 main_widgets_show_or_hide();
1281 statusbar_show_cb(GtkWidget *w _U_, gpointer d _U_)
1284 /* save current setting in recent */
1285 recent.statusbar_show = GTK_CHECK_MENU_ITEM(w)->active;
1287 main_widgets_show_or_hide();
1292 timestamp_absolute_cb(GtkWidget *w _U_, gpointer d _U_)
1294 if (recent.gui_time_format != TS_ABSOLUTE) {
1295 set_timestamp_setting(TS_ABSOLUTE);
1296 recent.gui_time_format = TS_ABSOLUTE;
1297 cf_change_time_formats(&cfile);
1302 timestamp_absolute_date_cb(GtkWidget *w _U_, gpointer d _U_)
1304 if (recent.gui_time_format != TS_ABSOLUTE_WITH_DATE) {
1305 set_timestamp_setting(TS_ABSOLUTE_WITH_DATE);
1306 recent.gui_time_format = TS_ABSOLUTE_WITH_DATE;
1307 cf_change_time_formats(&cfile);
1312 timestamp_relative_cb(GtkWidget *w _U_, gpointer d _U_)
1314 if (recent.gui_time_format != TS_RELATIVE) {
1315 set_timestamp_setting(TS_RELATIVE);
1316 recent.gui_time_format = TS_RELATIVE;
1317 cf_change_time_formats(&cfile);
1322 timestamp_delta_cb(GtkWidget *w _U_, gpointer d _U_)
1324 if (recent.gui_time_format != TS_DELTA) {
1325 set_timestamp_setting(TS_DELTA);
1326 recent.gui_time_format = TS_DELTA;
1327 cf_change_time_formats(&cfile);
1332 menu_name_resolution_changed(void)
1334 GtkWidget *menu = NULL;
1336 menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Name Resolution/Enable for MAC Layer");
1337 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), g_resolv_flags & RESOLV_MAC);
1339 menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Name Resolution/Enable for Network Layer");
1340 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), g_resolv_flags & RESOLV_NETWORK);
1342 menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Name Resolution/Enable for Transport Layer");
1343 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), g_resolv_flags & RESOLV_TRANSPORT);
1347 name_resolution_mac_cb(GtkWidget *w _U_, gpointer d _U_)
1349 if (GTK_CHECK_MENU_ITEM(w)->active) {
1350 g_resolv_flags |= RESOLV_MAC;
1352 g_resolv_flags &= ~RESOLV_MAC;
1357 name_resolution_network_cb(GtkWidget *w _U_, gpointer d _U_)
1359 if (GTK_CHECK_MENU_ITEM(w)->active) {
1360 g_resolv_flags |= RESOLV_NETWORK;
1362 g_resolv_flags &= ~RESOLV_NETWORK;
1367 name_resolution_transport_cb(GtkWidget *w _U_, gpointer d _U_)
1369 if (GTK_CHECK_MENU_ITEM(w)->active) {
1370 g_resolv_flags |= RESOLV_TRANSPORT;
1372 g_resolv_flags &= ~RESOLV_TRANSPORT;
1378 menu_auto_scroll_live_changed(gboolean auto_scroll_live_in) {
1382 /* tell menu about it */
1383 menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Auto Scroll in Live Capture");
1384 if( ((gboolean) GTK_CHECK_MENU_ITEM(menu)->active) != auto_scroll_live_in) {
1385 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), auto_scroll_live_in);
1388 /* tell toolbar about it */
1389 toolbar_auto_scroll_live_changed(auto_scroll_live_in);
1391 /* change auto scroll */
1392 if(auto_scroll_live_in != auto_scroll_live) {
1393 auto_scroll_live = auto_scroll_live_in;
1398 auto_scroll_live_cb(GtkWidget *w _U_, gpointer d _U_)
1400 menu_auto_scroll_live_changed(GTK_CHECK_MENU_ITEM(w)->active);
1406 menu_colorize_changed(gboolean packet_list_colorize) {
1410 /* tell menu about it */
1411 menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Colorize Packet List");
1412 if( ((gboolean) GTK_CHECK_MENU_ITEM(menu)->active) != packet_list_colorize) {
1413 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), packet_list_colorize);
1416 /* tell toolbar about it */
1417 toolbar_colorize_changed(packet_list_colorize);
1419 /* change colorization */
1420 if(packet_list_colorize != recent.packet_list_colorize) {
1421 recent.packet_list_colorize = packet_list_colorize;
1422 color_filters_enable(packet_list_colorize);
1423 cf_colorize_packets(&cfile);
1428 colorize_cb(GtkWidget *w, gpointer d _U_)
1430 menu_colorize_changed(GTK_CHECK_MENU_ITEM(w)->active);
1434 /* the recent file read has finished, update the menu corresponding */
1436 menu_recent_read_finished(void) {
1437 GtkWidget *menu = NULL;
1439 menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Main Toolbar");
1440 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), recent.main_toolbar_show);
1442 menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Filter Toolbar");
1443 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), recent.filter_toolbar_show);
1445 menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Statusbar");
1446 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), recent.statusbar_show);
1448 menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Packet List");
1449 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), recent.packet_list_show);
1451 menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Packet Details");
1452 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), recent.tree_view_show);
1454 menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Packet Bytes");
1455 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), recent.byte_view_show);
1457 menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Colorize Packet List");
1458 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), recent.packet_list_colorize);
1460 menu_name_resolution_changed();
1463 menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Auto Scroll in Live Capture");
1464 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), auto_scroll_live);
1467 main_widgets_rearrange();
1469 /* don't change the time format, if we had a command line value */
1470 if (get_timestamp_setting() != TS_NOT_SET) {
1471 recent.gui_time_format = get_timestamp_setting();
1474 switch(recent.gui_time_format) {
1476 menu = gtk_item_factory_get_widget(main_menu_factory,
1477 "/View/Time Display Format/Time of Day");
1478 /* set_active will not trigger the callback when activating an active item! */
1479 recent.gui_time_format = -1;
1480 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), FALSE);
1481 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), TRUE);
1483 case(TS_ABSOLUTE_WITH_DATE):
1484 menu = gtk_item_factory_get_widget(main_menu_factory,
1485 "/View/Time Display Format/Date and Time of Day");
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 Beginning of Capture");
1492 recent.gui_time_format = -1;
1493 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), TRUE);
1496 menu = gtk_item_factory_get_widget(main_menu_factory,
1497 "/View/Time Display Format/Seconds Since Previous Packet");
1498 recent.gui_time_format = -1;
1499 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), TRUE);
1502 g_assert_not_reached();
1505 menu_colorize_changed(recent.packet_list_colorize);
1510 popup_menu_handler(GtkWidget *widget, GdkEvent *event, gpointer data)
1512 GtkWidget *menu = (GtkWidget *)data;
1513 GdkEventButton *event_button = NULL;
1516 if(widget == NULL || event == NULL || data == NULL) {
1521 * If we ever want to make the menu differ based on what row
1522 * and/or column we're above, we'd use "eth_clist_get_selection_info()"
1523 * to find the row and column number for the coordinates; a CTree is,
1524 * I guess, like a CList with one column(?) and the expander widget
1527 /* Check if we are on packet_list object */
1528 if (widget == OBJECT_GET_DATA(popup_menu_object, E_MPACKET_LIST_KEY)) {
1529 if (packet_list_get_event_row_column(widget, (GdkEventButton *)event,
1531 OBJECT_SET_DATA(popup_menu_object, E_MPACKET_LIST_ROW_KEY,
1532 GINT_TO_POINTER(row));
1533 OBJECT_SET_DATA(popup_menu_object, E_MPACKET_LIST_COL_KEY,
1534 GINT_TO_POINTER(column));
1535 packet_list_set_selected_row(row);
1539 /* Check if we are on tree_view object */
1540 if (widget == tree_view) {
1541 tree_view_select(widget, (GdkEventButton *) event);
1544 /* Check if we are on byte_view object */
1545 if(widget == get_notebook_bv_ptr(byte_nb_ptr)) {
1546 byte_view_select(widget, (GdkEventButton *) event);
1549 /* context menu handler (but the byte view notebook pages have their own handler) */
1550 if(event->type == GDK_BUTTON_PRESS && widget != byte_nb_ptr) {
1551 event_button = (GdkEventButton *) event;
1553 /* To qoute the "Gdk Event Structures" doc:
1554 * "Normally button 1 is the left mouse button, 2 is the middle button, and 3 is the right button" */
1555 if(event_button->button == 3) {
1556 gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL,
1557 event_button->button,
1558 event_button->time);
1559 SIGNAL_EMIT_STOP_BY_NAME(widget, "button_press_event");
1563 #if GTK_MAJOR_VERSION >= 2
1564 /* GDK_2BUTTON_PRESS is a doubleclick -> expand/collapse tree row */
1565 /* GTK version 1 seems to be doing this automatically */
1566 if (widget == tree_view && event->type == GDK_2BUTTON_PRESS) {
1569 if (gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(widget),
1570 (gint) (((GdkEventButton *)event)->x),
1571 (gint) (((GdkEventButton *)event)->y),
1572 &path, NULL, NULL, NULL))
1574 if (gtk_tree_view_row_expanded(GTK_TREE_VIEW(widget), path))
1575 gtk_tree_view_collapse_row(GTK_TREE_VIEW(widget), path);
1577 gtk_tree_view_expand_row(GTK_TREE_VIEW(widget), path,
1579 gtk_tree_path_free(path);
1586 /* Enable or disable menu items based on whether you have a capture file
1587 you've finished reading. */
1589 set_menus_for_capture_file(gboolean have_capture_file)
1591 set_menu_sensitivity(main_menu_factory, "/File/Open...", have_capture_file);
1592 set_menu_sensitivity(main_menu_factory, "/File/Open Recent", have_capture_file);
1593 set_menu_sensitivity(main_menu_factory, "/File/Merge...", have_capture_file);
1594 set_menu_sensitivity(main_menu_factory, "/File/Close", have_capture_file);
1595 set_menu_sensitivity(main_menu_factory, "/File/Save As...",
1597 set_menu_sensitivity(main_menu_factory, "/File/Export", have_capture_file);
1598 set_menu_sensitivity(main_menu_factory, "/View/Reload", have_capture_file);
1599 set_toolbar_for_capture_file(have_capture_file);
1600 packets_bar_update();
1603 /* Enable or disable menu items based on whether you have an unsaved
1604 capture file you've finished reading. */
1606 set_menus_for_unsaved_capture_file(gboolean have_unsaved_capture_file)
1608 set_menu_sensitivity(main_menu_factory, "/File/Save",
1609 have_unsaved_capture_file);
1610 set_toolbar_for_unsaved_capture_file(have_unsaved_capture_file);
1613 /* Enable or disable menu items based on whether there's a capture in
1616 set_menus_for_capture_in_progress(gboolean capture_in_progress)
1618 set_menu_sensitivity(main_menu_factory, "/File/Open...",
1619 !capture_in_progress);
1620 set_menu_sensitivity(main_menu_factory, "/File/Open Recent",
1621 !capture_in_progress);
1623 set_menu_sensitivity(main_menu_factory, "/Capture/Options...",
1624 !capture_in_progress);
1625 set_menu_sensitivity(main_menu_factory, "/Capture/Start",
1626 !capture_in_progress);
1627 set_menu_sensitivity(main_menu_factory, "/Capture/Stop",
1628 capture_in_progress);
1629 set_menu_sensitivity(main_menu_factory, "/Capture/Restart",
1630 capture_in_progress);
1631 set_toolbar_for_capture_in_progress(capture_in_progress);
1633 set_capture_if_dialog_for_capture_in_progress(capture_in_progress);
1634 #endif /* HAVE_LIBPCAP */
1637 /* Enable or disable menu items based on whether you have some captured
1640 walk_menu_tree_for_captured_packets(GList *node,
1641 gboolean have_captured_packets)
1643 gboolean is_enabled;
1645 menu_item_t *node_data = node->data;
1648 * Is this a leaf node or an interior node?
1650 if (node_data->children == NULL) {
1654 * If it has no "selected_packet_enabled()" or
1655 * "selected_tree_row_enabled()" routines, we enable
1656 * it. This allows tap windows to be popped up even
1657 * if you have no capture file; this is done to let
1658 * the user pop up multiple tap windows before reading
1659 * in a capture file, so that they can be processed in
1660 * parallel while the capture file is being read rather
1661 * than one at at time as you pop up the windows, and to
1662 * let the user pop up tap windows before starting an
1663 * "Update list of packets in real time" capture, so that
1664 * the statistics can be displayed while the capture is
1667 * If it has either of those routines, we disable it for
1668 * now - as long as, when a capture is first available,
1669 * we don't get called after a packet or tree row is
1670 * selected, that's OK.
1671 * XXX - that should be done better.
1673 if (node_data->selected_packet_enabled == NULL &&
1674 node_data->selected_tree_row_enabled == NULL)
1675 node_data->enabled = TRUE;
1677 node_data->enabled = FALSE;
1680 * It's an interior node; call
1681 * "walk_menu_tree_for_captured_packets()" on all its
1682 * children and, if any of them are enabled, enable
1683 * this node, otherwise disable it.
1685 * XXX - should we just leave all interior nodes enabled?
1686 * Which is a better UI choice?
1689 for (child = node_data->children; child != NULL; child =
1691 if (walk_menu_tree_for_captured_packets(child,
1692 have_captured_packets))
1695 node_data->enabled = is_enabled;
1699 * The root node doesn't correspond to a menu tree item; it
1700 * has a null name pointer.
1702 if (node_data->name != NULL) {
1703 set_menu_sensitivity(main_menu_factory, node_data->name,
1704 node_data->enabled);
1706 return node_data->enabled;
1710 set_menus_for_captured_packets(gboolean have_captured_packets)
1712 set_menu_sensitivity(main_menu_factory, "/File/Print...",
1713 have_captured_packets);
1714 set_menu_sensitivity(packet_list_menu_factory, "/Print...",
1715 have_captured_packets);
1716 set_menu_sensitivity(main_menu_factory, "/Edit/Find Packet...",
1717 have_captured_packets);
1718 set_menu_sensitivity(main_menu_factory, "/Edit/Find Next",
1719 have_captured_packets);
1720 set_menu_sensitivity(main_menu_factory, "/Edit/Find Previous",
1721 have_captured_packets);
1722 set_menu_sensitivity(main_menu_factory, "/View/Zoom In",
1723 have_captured_packets);
1724 set_menu_sensitivity(main_menu_factory, "/View/Zoom Out",
1725 have_captured_packets);
1726 set_menu_sensitivity(main_menu_factory, "/View/Normal Size",
1727 have_captured_packets);
1728 set_menu_sensitivity(main_menu_factory, "/Go/Go to Packet...",
1729 have_captured_packets);
1730 set_menu_sensitivity(main_menu_factory, "/Go/First Packet",
1731 have_captured_packets);
1732 set_menu_sensitivity(main_menu_factory, "/Go/Last Packet",
1733 have_captured_packets);
1734 set_menu_sensitivity(main_menu_factory, "/Statistics/Summary",
1735 have_captured_packets);
1736 set_menu_sensitivity(main_menu_factory, "/Statistics/Protocol Hierarchy",
1737 have_captured_packets);
1739 walk_menu_tree_for_captured_packets(tap_menu_tree_root,
1740 have_captured_packets);
1741 set_toolbar_for_captured_packets(have_captured_packets);
1742 packets_bar_update();
1745 /* Enable or disable menu items based on whether a packet is selected and,
1746 if so, on the properties of the packet. */
1748 walk_menu_tree_for_selected_packet(GList *node, frame_data *fd,
1749 epan_dissect_t *edt)
1751 gboolean is_enabled;
1753 menu_item_t *node_data = node->data;
1756 * Is this a leaf node or an interior node?
1758 if (node_data->children == NULL) {
1762 * If it has no "selected_packet_enabled()" routine,
1763 * leave its enabled/disabled status alone - it
1764 * doesn't depend on whether we have a packet selected
1765 * or not or on the selected packet.
1767 * If it has a "selected_packet_enabled()" routine,
1768 * call it and set the item's enabled/disabled status
1769 * based on its return value.
1771 if (node_data->selected_packet_enabled != NULL)
1772 node_data->enabled = node_data->selected_packet_enabled(fd, edt);
1775 * It's an interior node; call
1776 * "walk_menu_tree_for_selected_packet()" on all its
1777 * children and, if any of them are enabled, enable
1778 * this node, otherwise disable it.
1780 * XXX - should we just leave all interior nodes enabled?
1781 * Which is a better UI choice?
1784 for (child = node_data->children; child != NULL; child =
1786 if (walk_menu_tree_for_selected_packet(child, fd, edt))
1789 node_data->enabled = is_enabled;
1793 * The root node doesn't correspond to a menu tree item; it
1794 * has a null name pointer.
1796 if (node_data->name != NULL) {
1797 set_menu_sensitivity(main_menu_factory, node_data->name,
1798 node_data->enabled);
1800 return node_data->enabled;
1804 set_menus_for_selected_packet(capture_file *cf)
1806 set_menu_sensitivity(main_menu_factory, "/Edit/Mark Packet (toggle)",
1807 cf->current_frame != NULL);
1808 set_menu_sensitivity(packet_list_menu_factory, "/Mark Packet (toggle)",
1809 cf->current_frame != NULL);
1810 set_menu_sensitivity(main_menu_factory, "/Edit/Time Reference",
1811 cf->current_frame != NULL);
1812 set_menu_sensitivity(packet_list_menu_factory, "/Time Reference",
1813 cf->current_frame != NULL);
1814 set_menu_sensitivity(main_menu_factory, "/Edit/Mark All Packets",
1815 cf->current_frame != NULL);
1816 set_menu_sensitivity(main_menu_factory, "/Edit/Unmark All Packets",
1817 cf->current_frame != NULL);
1818 set_menu_sensitivity(main_menu_factory, "/View/Resize All Columns",
1819 cf->current_frame != NULL);
1820 set_menu_sensitivity(main_menu_factory, "/View/Collapse All",
1821 cf->current_frame != NULL);
1822 set_menu_sensitivity(tree_view_menu_factory, "/Collapse All",
1823 cf->current_frame != NULL);
1824 set_menu_sensitivity(main_menu_factory, "/View/Expand All",
1825 cf->current_frame != NULL);
1826 set_menu_sensitivity(tree_view_menu_factory, "/Expand All",
1827 cf->current_frame != NULL);
1828 set_menu_sensitivity(main_menu_factory, "/View/Show Packet in New Window",
1829 cf->current_frame != NULL);
1830 set_menu_sensitivity(packet_list_menu_factory, "/Show Packet in New Window",
1831 cf->current_frame != NULL);
1832 set_menu_sensitivity(main_menu_factory, "/Analyze/Follow TCP Stream",
1833 cf->current_frame != NULL ? (cf->edt->pi.ipproto == IP_PROTO_TCP) : FALSE);
1834 set_menu_sensitivity(packet_list_menu_factory, "/Follow TCP Stream",
1835 cf->current_frame != NULL ? (cf->edt->pi.ipproto == IP_PROTO_TCP) : FALSE);
1836 set_menu_sensitivity(tree_view_menu_factory, "/Follow TCP Stream",
1837 cf->current_frame != NULL ? (cf->edt->pi.ipproto == IP_PROTO_TCP) : FALSE);
1838 set_menu_sensitivity(main_menu_factory, "/Analyze/Decode As...",
1839 cf->current_frame != NULL && decode_as_ok());
1840 set_menu_sensitivity(packet_list_menu_factory, "/Decode As...",
1841 cf->current_frame != NULL && decode_as_ok());
1842 set_menu_sensitivity(tree_view_menu_factory, "/Decode As...",
1843 cf->current_frame != NULL && decode_as_ok());
1844 set_menu_sensitivity(main_menu_factory, "/View/Name Resolution/Resolve Name",
1845 cf->current_frame != NULL && (g_resolv_flags & RESOLV_ALL_ADDRS) != RESOLV_ALL_ADDRS);
1846 set_menu_sensitivity(tree_view_menu_factory, "/Resolve Name",
1847 cf->current_frame != NULL && (g_resolv_flags & RESOLV_ALL_ADDRS) != RESOLV_ALL_ADDRS);
1848 set_menu_sensitivity(packet_list_menu_factory, "/Apply as Filter",
1849 cf->current_frame != NULL);
1850 set_menu_sensitivity(packet_list_menu_factory, "/Prepare a Filter",
1851 cf->current_frame != NULL);
1853 walk_menu_tree_for_selected_packet(tap_menu_tree_root, cf->current_frame,
1855 packets_bar_update();
1858 /* Enable or disable menu items based on whether a tree row is selected
1859 and, if so, on the properties of the tree row. */
1861 walk_menu_tree_for_selected_tree_row(GList *node, field_info *fi)
1863 gboolean is_enabled;
1865 menu_item_t *node_data = node->data;
1868 * Is this a leaf node or an interior node?
1870 if (node_data->children == NULL) {
1874 * If it has no "selected_tree_row_enabled()" routine,
1875 * leave its enabled/disabled status alone - it
1876 * doesn't depend on whether we have a tree row selected
1877 * or not or on the selected tree row.
1879 * If it has a "selected_tree_row_enabled()" routine,
1880 * call it and set the item's enabled/disabled status
1881 * based on its return value.
1883 if (node_data->selected_tree_row_enabled != NULL)
1884 node_data->enabled = node_data->selected_tree_row_enabled(fi);
1887 * It's an interior node; call
1888 * "walk_menu_tree_for_selected_tree_row()" on all its
1889 * children and, if any of them are enabled, enable
1890 * this node, otherwise disable it.
1892 * XXX - should we just leave all interior nodes enabled?
1893 * Which is a better UI choice?
1896 for (child = node_data->children; child != NULL; child =
1898 if (walk_menu_tree_for_selected_tree_row(child, fi))
1901 node_data->enabled = is_enabled;
1905 * The root node doesn't correspond to a menu tree item; it
1906 * has a null name pointer.
1908 if (node_data->name != NULL) {
1909 set_menu_sensitivity(main_menu_factory, node_data->name,
1910 node_data->enabled);
1912 return node_data->enabled;
1916 set_menus_for_selected_tree_row(capture_file *cf)
1918 gboolean properties;
1921 set_menu_sensitivity(main_menu_factory, "/File/Export/Selected Packet Bytes...",
1922 cf->finfo_selected != NULL);
1923 set_menu_sensitivity(hexdump_menu_factory, "/Copy",
1924 cf->finfo_selected != NULL);
1925 set_menu_sensitivity(hexdump_menu_factory, "/Export Selected Packet Bytes...",
1926 cf->finfo_selected != NULL);
1928 if (cf->finfo_selected != NULL) {
1929 header_field_info *hfinfo = cf->finfo_selected->hfinfo;
1930 if (hfinfo->parent == -1) {
1931 properties = prefs_is_registered_protocol(hfinfo->abbrev);
1933 properties = prefs_is_registered_protocol(proto_registrar_get_abbrev(hfinfo->parent));
1935 set_menu_sensitivity(main_menu_factory,
1936 "/Go/Go to Corresponding Packet", hfinfo->type == FT_FRAMENUM);
1937 set_menu_sensitivity(tree_view_menu_factory,
1938 "/Go to Corresponding Packet", hfinfo->type == FT_FRAMENUM);
1939 set_menu_sensitivity(main_menu_factory, "/Analyze/Apply as Filter",
1940 proto_can_match_selected(cf->finfo_selected, cf->edt));
1941 set_menu_sensitivity(tree_view_menu_factory, "/Apply as Filter",
1942 proto_can_match_selected(cf->finfo_selected, cf->edt));
1943 set_menu_sensitivity(main_menu_factory, "/Analyze/Prepare a Filter",
1944 proto_can_match_selected(cf->finfo_selected, cf->edt));
1945 set_menu_sensitivity(tree_view_menu_factory, "/Prepare a Filter",
1946 proto_can_match_selected(cf->finfo_selected, cf->edt));
1947 set_menu_sensitivity(tree_view_menu_factory, "/Protocol Preferences...",
1949 set_menu_sensitivity(main_menu_factory, "/View/Expand Subtrees", cf->finfo_selected->tree_type != -1);
1950 set_menu_sensitivity(tree_view_menu_factory, "/Expand Subtrees", cf->finfo_selected->tree_type != -1);
1951 set_menu_sensitivity(tree_view_menu_factory, "/Wiki Protocol Page",
1953 set_menu_sensitivity(tree_view_menu_factory, "/Filter Field Reference",
1956 set_menu_sensitivity(main_menu_factory,
1957 "/Go/Go to Corresponding Packet", FALSE);
1958 set_menu_sensitivity(tree_view_menu_factory,
1959 "/Go to Corresponding Packet", FALSE);
1960 set_menu_sensitivity(main_menu_factory, "/Analyze/Apply as Filter", FALSE);
1961 set_menu_sensitivity(tree_view_menu_factory, "/Apply as Filter", FALSE);
1962 set_menu_sensitivity(main_menu_factory, "/Analyze/Prepare a Filter", FALSE);
1963 set_menu_sensitivity(tree_view_menu_factory, "/Prepare a Filter", FALSE);
1964 set_menu_sensitivity(tree_view_menu_factory, "/Protocol Preferences...",
1966 set_menu_sensitivity(main_menu_factory, "/View/Expand Subtrees", FALSE);
1967 set_menu_sensitivity(tree_view_menu_factory, "/Expand Subtrees", FALSE);
1968 set_menu_sensitivity(tree_view_menu_factory, "/Wiki Protocol Page",
1970 set_menu_sensitivity(tree_view_menu_factory, "/Filter Field Reference",
1974 walk_menu_tree_for_selected_tree_row(tap_menu_tree_root, cf->finfo_selected);
1977 void set_menus_for_packet_history(gboolean back_history, gboolean forward_history) {
1979 set_menu_sensitivity(main_menu_factory, "/Go/Back", back_history);
1980 set_menu_sensitivity(main_menu_factory, "/Go/Forward", forward_history);
1982 set_toolbar_for_packet_history(back_history, forward_history);
1986 void set_menus_for_file_set(gboolean file_set, gboolean previous_file, gboolean next_file) {
1988 set_menu_sensitivity(main_menu_factory, "/File/File Set/List Files", file_set);
1989 set_menu_sensitivity(main_menu_factory, "/File/File Set/Previous File", previous_file);
1990 set_menu_sensitivity(main_menu_factory, "/File/File Set/Next File", next_file);