as the "Firewall ACL rules" perfectly fits into a tools menu, and together with the...
[obnox/wireshark/wip.git] / gtk / main_menu.c
1 /* main_menu.c
2  * Main menu routines
3  *
4  * $Id$
5  *
6  * Wireshark - Network traffic analyzer
7  * By Gerald Combs <gerald@wireshark.org>
8  * Copyright 1998 Gerald Combs
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License
12  * as published by the Free Software Foundation; either version 2
13  * of the License, or (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
23  */
24
25 #ifdef HAVE_CONFIG_H
26 # include "config.h"
27 #endif
28
29 #include <gtk/gtk.h>
30
31 #include <string.h>
32
33 #include <epan/packet.h>
34 #include <epan/addr_resolv.h>
35 #include <epan/prefs.h>
36 #include <epan/tap.h>
37 #include <epan/timestamp.h>
38 #include <epan/ipproto.h>
39 #include <epan/dissector_filters.h>
40 #include <epan/strutil.h>
41 #include <epan/plugins.h>
42 #include <epan/epan_dissect.h>
43
44 #include "../print.h"
45 #include "../register.h"
46 #include "../ui_util.h"
47 #include "../simple_dialog.h"
48 #include "../color_filters.h"
49 #include "../stat_menu.h"
50
51 #include "gtk/about_dlg.h"
52 #include "gtk/capture_dlg.h"
53 #include "gtk/color_dlg.h"
54 #include "gtk/filter_dlg.h"
55 #include "gtk/profile_dlg.h"
56 #include "gtk/dlg_utils.h"
57 #include "gtk/capture_file_dlg.h"
58 #include "gtk/fileset_dlg.h"
59 #include "gtk/find_dlg.h"
60 #include "gtk/goto_dlg.h"
61 #include "gtk/summary_dlg.h"
62 #include "gtk/prefs_dlg.h"
63 #include "gtk/packet_win.h"
64 #include "gtk/follow_tcp.h"
65 #include "gtk/follow_udp.h"
66 #include "gtk/follow_ssl.h"
67 #include "gtk/decode_as_dlg.h"
68 #include "gtk/help_dlg.h"
69 #include "gtk/supported_protos_dlg.h"
70 #include "gtk/proto_dlg.h"
71 #include "gtk/proto_hier_stats_dlg.h"
72 #include "gtk/keys.h"
73 #include "gtk/stock_icons.h"
74 #include "gtk/gtkglobals.h"
75 #include "gtk/recent.h"
76 #include "gtk/main_proto_draw.h"
77 #include "gtk/conversations_table.h"
78 #include "gtk/hostlist_table.h"
79 #include "gtk/packet_history.h"
80 #include "gtk/sctp_stat.h"
81 #include "gtk/firewall_dlg.h"
82 #include "gtk/u3.h"
83 #include "gtk/macros_dlg.h"
84 #include "gtk/export_object.h"
85 #include "gtk/gui_stat_menu.h"
86 #include "gtk/main.h"
87 #include "gtk/main_menu.h"
88 #include "gtk/main_packet_list.h"
89 #include "gtk/main_toolbar.h"
90
91
92 typedef struct _menu_item {
93     char    *name;
94     gint    group;
95     const char *stock_id;
96     gboolean enabled;
97     GtkItemFactoryCallback callback;
98     gpointer callback_data;
99     gboolean (*selected_packet_enabled)(frame_data *, epan_dissect_t *, gpointer callback_data);
100     gboolean (*selected_tree_row_enabled)(field_info *, gpointer callback_data);
101     GList *children;
102 } menu_item_t;
103
104 static GList *tap_menu_tree_root = NULL;
105
106 GtkWidget *popup_menu_object;
107
108
109 #define GTK_MENU_FUNC(a) ((GtkItemFactoryCallback)(a))
110
111 static void merge_all_tap_menus(GList *node);
112 static void clear_menu_recent_capture_file_cmd_cb(GtkWidget *w, gpointer unused _U_);
113
114 static void menus_init(void);
115 static void set_menu_sensitivity (GtkItemFactory *, const gchar *, gint);
116 static void show_hide_cb(GtkWidget *w, gpointer data, gint action);
117 static void timestamp_format_cb(GtkWidget *w, gpointer d, gint action);
118 static void timestamp_precision_cb(GtkWidget *w, gpointer d, gint action);
119 static void name_resolution_cb(GtkWidget *w, gpointer d, gint action);
120 #ifdef HAVE_LIBPCAP
121 static void auto_scroll_live_cb(GtkWidget *w, gpointer d);
122 #endif
123 static void colorize_cb(GtkWidget *w, gpointer d);
124
125
126 /* This is the GtkItemFactoryEntry structure used to generate new menus.
127        Item 1: The menu path. The letter after the underscore indicates an
128                accelerator key once the menu is open.
129        Item 2: The accelerator key for the entry
130        Item 3: The callback function.
131        Item 4: The callback action.  This changes the parameters with
132                which the function is called.  The default is 0.
133        Item 5: The item type, used to define what kind of an item it is.
134                Here are the possible values:
135
136                NULL               -> "<Item>"
137                ""                 -> "<Item>"
138                "<Title>"          -> create a title item
139                "<Item>"           -> create a simple item
140                "<ImageItem>"      -> create an item holding an image (gtk2)
141                "<StockItem>"      -> create an item holding a stock image (gtk2)
142                "<CheckItem>"      -> create a check item
143                "<ToggleItem>"     -> create a toggle item
144                "<RadioItem>"      -> create a radio item
145                <path>             -> path of a radio item to link against
146                "<Separator>"      -> create a separator
147                "<Tearoff>"        -> create a tearoff separator (gtk2)
148                "<Branch>"         -> create an item to hold sub items (optional)
149                "<LastBranch>"     -> create a right justified branch
150        Item 6: extra data needed for ImageItem and StockItem (gtk2)
151     */
152
153 /*  As a general GUI guideline, we try to follow the Gnome Human Interface Guidelines, which can be found at:
154     http://developer.gnome.org/projects/gup/hig/1.0/index.html
155
156 Please note: there are some differences between the Gnome HIG menu suggestions and our implementation:
157
158 File/Open Recent:   the Gnome HIG suggests putting the list of recently used files as elements into the File menuitem.
159                     As this is ok for only a few items, this will become unhandy for 10 or even more list entries.
160                     For this reason, we use a submenu for this.
161
162 File/Close:         the Gnome HIG suggests putting this item just above the Quit item.
163                     This results in unintuitive behaviour as both Close and Quit items are very near together.
164                     By putting the Close item near the open item(s), it better suggests that it will close the
165                     currently opened/captured file only.
166 */
167
168 typedef enum {
169     SHOW_HIDE_MAIN_TOOLBAR = 1,
170     SHOW_HIDE_FILTER_TOOLBAR,
171     SHOW_HIDE_AIRPCAP_TOOLBAR,
172     SHOW_HIDE_STATUSBAR,
173     SHOW_HIDE_PACKET_LIST,
174     SHOW_HIDE_TREE_VIEW,
175     SHOW_HIDE_BYTE_VIEW
176 } show_hide_values_e;
177
178 typedef enum {
179     CONV_ETHER = 1,
180     CONV_IP,
181     CONV_TCP,
182     CONV_UDP,
183     CONV_CBA
184 } conv_values_e;
185
186 char *
187 build_conversation_filter(int action, gboolean show_dialog)
188 {
189     packet_info *pi = &cfile.edt->pi;
190     char        *buf;
191
192
193     switch(action) {
194     case(CONV_CBA):
195         if (pi->profinet_type == 0) {
196             if (show_dialog) {
197                 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
198                     "Error filtering conversation.  Please make\n"
199                     "sure you have a PROFINET CBA packet selected.");
200             }
201             return NULL;
202         }
203
204         if( pi->net_src.type == AT_IPv4 && pi->net_dst.type == AT_IPv4
205         && pi->ipproto == 6 ) {
206             /* IPv4 */
207             switch(pi->profinet_type) {
208             case(1):
209                 buf = g_strdup_printf("(ip.src eq %s and ip.dst eq %s and cba.acco.dcom == 1) || (ip.src eq %s and ip.dst eq %s and cba.acco.dcom == 0)",
210                     ip_to_str( pi->net_dst.data),
211                     ip_to_str( pi->net_src.data),
212                     ip_to_str( pi->net_src.data),
213                     ip_to_str( pi->net_dst.data));
214                 break;
215             case(2):
216                 buf = g_strdup_printf("(ip.src eq %s and ip.dst eq %s and cba.acco.dcom == 1) || (ip.src eq %s and ip.dst eq %s and cba.acco.dcom == 0)",
217                     ip_to_str( pi->net_src.data),
218                     ip_to_str( pi->net_dst.data),
219                     ip_to_str( pi->net_dst.data),
220                     ip_to_str( pi->net_src.data));
221                 break;
222             case(3):
223                 buf = g_strdup_printf("(ip.src eq %s and ip.dst eq %s and cba.acco.srt == 1) || (ip.src eq %s and ip.dst eq %s and cba.acco.srt == 0)",
224                     ip_to_str( pi->net_dst.data),
225                     ip_to_str( pi->net_src.data),
226                     ip_to_str( pi->net_src.data),
227                     ip_to_str( pi->net_dst.data));
228                 break;
229             case(4):
230                 buf = g_strdup_printf("(ip.src eq %s and ip.dst eq %s and cba.acco.srt == 1) || (ip.src eq %s and ip.dst eq %s and cba.acco.srt == 0)",
231                     ip_to_str( pi->net_src.data),
232                     ip_to_str( pi->net_dst.data),
233                     ip_to_str( pi->net_dst.data),
234                     ip_to_str( pi->net_src.data));
235                 break;
236             default:
237                 return NULL;
238             }
239         } else {
240             return NULL;
241         }
242         break;
243     case(CONV_TCP):
244         if (cfile.edt->pi.ipproto != IP_PROTO_TCP) {
245             if (show_dialog) {
246                 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
247                     "Error filtering conversation.  Please make\n"
248                     "sure you have a TCP packet selected.");
249             }
250             return NULL;
251         }
252
253         if( pi->net_src.type == AT_IPv4 && pi->net_dst.type == AT_IPv4
254         && pi->ipproto == 6 ) {
255             /* TCP over IPv4 */
256             buf = g_strdup_printf("(ip.addr eq %s and ip.addr eq %s) and (tcp.port eq %d and tcp.port eq %d)",
257                 ip_to_str( pi->net_src.data),
258                 ip_to_str( pi->net_dst.data),
259                 pi->srcport, pi->destport );
260         } else if( pi->net_src.type == AT_IPv6 && pi->net_dst.type == AT_IPv6
261                 && pi->ipproto == 6 ) {
262             /* TCP over IPv6 */
263             buf = g_strdup_printf("(ipv6.addr eq %s and ipv6.addr eq %s) and (tcp.port eq %d and tcp.port eq %d)",
264                 ip6_to_str((const struct e_in6_addr *)pi->net_src.data),
265                 ip6_to_str((const struct e_in6_addr *)pi->net_dst.data),
266                 pi->srcport, pi->destport );
267         } else {
268             return NULL;
269         }
270         break;
271     case(CONV_UDP):
272         if (cfile.edt->pi.ipproto != IP_PROTO_UDP) {
273             if (show_dialog) {
274                 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
275                     "Error filtering conversation.  Please make\n"
276                     "sure you have a UDP packet selected.");
277             }
278             return NULL;
279         }
280
281         if( pi->net_src.type == AT_IPv4 && pi->net_dst.type == AT_IPv4
282         && pi->ipproto == IP_PROTO_UDP /*6*/ ) {
283             /* UDP over IPv4 */
284             buf = g_strdup_printf("(ip.addr eq %s and ip.addr eq %s) and (udp.port eq %d and udp.port eq %d)",
285                 ip_to_str( pi->net_src.data),
286                 ip_to_str( pi->net_dst.data),
287                 pi->srcport, pi->destport );
288         } else if( pi->net_src.type == AT_IPv6 && pi->net_dst.type == AT_IPv6
289                 && pi->ipproto == IP_PROTO_UDP /*6*/ ) {
290             /* UDP over IPv6 */
291             buf = g_strdup_printf("(ipv6.addr eq %s and ipv6.addr eq %s) and (udp.port eq %d and udp.port eq %d)",
292                 ip6_to_str((const struct e_in6_addr *)pi->net_src.data),
293                 ip6_to_str((const struct e_in6_addr *)pi->net_dst.data),
294                 pi->srcport, pi->destport );
295         } else {
296             return NULL;
297         }
298         break;
299     case(CONV_IP):
300         if (cfile.edt->pi.ethertype != 0x800) {
301             if (show_dialog) {
302                 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
303                     "Error filtering conversation.  Please make\n"
304                     "sure you have a IP packet selected.");
305             }
306             return NULL;
307         }
308
309         if( pi->net_src.type == AT_IPv4 && pi->net_dst.type == AT_IPv4
310         && pi->ipproto == 6 ) {
311             /* IPv4 */
312             buf = g_strdup_printf("ip.addr eq %s and ip.addr eq %s",
313                 ip_to_str( pi->net_src.data),
314                 ip_to_str( pi->net_dst.data));
315         } else if( pi->net_src.type == AT_IPv6 && pi->net_dst.type == AT_IPv6
316                 && pi->ipproto == 6 ) {
317             /* IPv6 */
318             buf = g_strdup_printf("ipv6.addr eq %s and ipv6.addr eq %s",
319                 ip6_to_str((const struct e_in6_addr *)pi->net_src.data),
320                 ip6_to_str((const struct e_in6_addr *)pi->net_dst.data));
321         } else {
322             return NULL;
323         }
324         break;
325     case(CONV_ETHER):
326         /* XXX - is this the right way to check for Ethernet? */
327         /* check for the data link address type */
328         /* (ethertype will be 0 when used as length field) */
329         if (cfile.edt->pi.dl_src.type != 1) {
330             if (show_dialog) {
331                 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
332                     "Error filtering conversation.  Please make\n"
333                     "sure you have a Ethernet packet selected.");
334             }
335             return NULL;
336         }
337
338         if( pi->dl_src.type == 1 /*AT_IPv4*/ && pi->dl_dst.type == 1 /*AT_IPv4*/) {
339             /* Ethernet */
340             buf = g_strdup_printf("eth.addr eq %s and eth.addr eq %s",
341                 ether_to_str( pi->dl_src.data),
342                 ether_to_str( pi->dl_dst.data));
343         } else {
344             return NULL;
345         }
346         break;
347     default:
348         return NULL;
349     }
350
351     return buf;
352 }
353
354 void
355 conversation_cb(GtkWidget * w, gpointer data _U_, int action)
356 {
357     gchar       *filter;
358     GtkWidget   *filter_te;
359
360     if (cfile.current_frame) {
361         /* create a filter-string based on the selected packet and action */
362         filter = build_conversation_filter(action, TRUE);
363
364         /* Run the display filter so it goes in effect - even if it's the
365         same as the previous display filter. */
366         filter_te = g_object_get_data(G_OBJECT(w), E_DFILTER_TE_KEY);
367         gtk_entry_set_text(GTK_ENTRY(filter_te), filter);
368         main_filter_packets(&cfile, filter, TRUE);
369
370         g_free(filter);
371     }
372 }
373
374 void
375 colorize_conversation_cb(GtkWidget * w _U_, gpointer data _U_, int action)
376 {
377     gchar        *filter = NULL;
378
379     if( (action>>8) == 255 ) {
380         color_filters_reset_tmp();
381         cf_colorize_packets(&cfile);
382     } else if (cfile.current_frame) {
383         if( (action&0xff) == 0 ) {
384             /* colorize_conversation_cb was called from the window-menu
385              * or through an accelerator key. Try to build a conversation
386              * filter in the order TCP, UDP, IP, Ethernet and apply the
387              * coloring */
388             filter = build_conversation_filter(CONV_TCP,FALSE);
389             if( filter == NULL )
390                 filter = build_conversation_filter(CONV_UDP,FALSE);
391             if( filter == NULL )
392                 filter = build_conversation_filter(CONV_IP,FALSE);
393             if( filter == NULL )
394                 filter = build_conversation_filter(CONV_ETHER,FALSE);
395             if( filter == NULL ) {
396                 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Unable to build conversation filter.");
397                 return;
398             }
399         } else {
400             /* create a filter-string based on the selected packet and action */
401             filter = build_conversation_filter(action&0xff, TRUE);
402         }
403
404         if( (action>>8) == 0) {
405             /* Open the "new coloring filter" dialog with the filter */
406             color_display_with_filter(filter);
407         } else {
408             /* Set one of the temporary coloring filters */
409             color_filters_set_tmp((guint8)(action>>8),filter,FALSE);
410             cf_colorize_packets(&cfile);
411         }
412
413         g_free(filter);
414     }
415 }
416
417 /* main menu */
418 static GtkItemFactoryEntry menu_items[] =
419 {
420     {"/_File", NULL, NULL, 0, "<Branch>", NULL,},
421     {"/File/_Open...", "<control>O", GTK_MENU_FUNC(file_open_cmd_cb),
422                              0, "<StockItem>", GTK_STOCK_OPEN,},
423     {"/File/Open _Recent", NULL, NULL, 0, "<Branch>", NULL,},
424     {"/File/_Merge...", NULL, GTK_MENU_FUNC(file_merge_cmd_cb), 0, NULL, NULL,},
425     {"/File/_Close", "<control>W", GTK_MENU_FUNC(file_close_cmd_cb),
426                              0, "<StockItem>", GTK_STOCK_CLOSE,},
427     {"/File/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
428     {"/File/_Save", "<control>S", GTK_MENU_FUNC(file_save_cmd_cb),
429                              0, "<StockItem>", GTK_STOCK_SAVE,},
430     {"/File/Save _As...", "<shift><control>S", GTK_MENU_FUNC(file_save_as_cmd_cb),
431                              0, "<StockItem>", GTK_STOCK_SAVE_AS,},
432     {"/File/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
433     {"/File/File Set", NULL, NULL, 0, "<Branch>", NULL,},
434     {"/File/File Set/List Files", NULL, GTK_MENU_FUNC(fileset_cb), 0, "<StockItem>", WIRESHARK_STOCK_FILE_SET_LIST,},
435     {"/File/File Set/Next File", NULL, GTK_MENU_FUNC(fileset_next_cb), 0, "<StockItem>", WIRESHARK_STOCK_FILE_SET_NEXT,},
436     {"/File/File Set/Previous File", NULL, GTK_MENU_FUNC(fileset_previous_cb), 0, "<StockItem>", WIRESHARK_STOCK_FILE_SET_PREVIOUS,},
437     {"/File/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
438     {"/File/_Export", NULL, NULL, 0, "<Branch>", NULL,},
439 #if _WIN32
440     {"/File/Export/File...", NULL, GTK_MENU_FUNC(export_text_cmd_cb),
441                          0, NULL, NULL,},
442 #else
443     {"/File/Export/as \"Plain _Text\" file...", NULL, GTK_MENU_FUNC(export_text_cmd_cb),
444                              0, NULL, NULL,},
445     {"/File/Export/as \"_PostScript\" file...", NULL, GTK_MENU_FUNC(export_ps_cmd_cb),
446                              0, NULL, NULL,},
447     {"/File/Export/as \"_CSV\" (Comma Separated Values packet summary) file...",
448                              NULL, GTK_MENU_FUNC(export_csv_cmd_cb), 0, NULL, NULL,},
449     {"/File/Export/as \"C _Arrays\" (packet bytes) file...", NULL, GTK_MENU_FUNC(export_carrays_cmd_cb),
450                              0, NULL, NULL,},
451     {"/File/Export/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
452     {"/File/Export/as XML - \"P_SML\" (packet summary) file...", NULL, GTK_MENU_FUNC(export_psml_cmd_cb),
453                              0, NULL, NULL,},
454     {"/File/Export/as XML - \"P_DML\" (packet details) file...", NULL, GTK_MENU_FUNC(export_pdml_cmd_cb),
455                              0, NULL, NULL,},
456     {"/File/Export/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
457 #endif
458     {"/File/Export/Selected Packet _Bytes...", "<control>H", GTK_MENU_FUNC(savehex_cb),
459                              0, NULL, NULL,},
460 #if GTK_CHECK_VERSION(2,4,0)
461     {"/File/Export/_Objects/_HTTP", NULL, GTK_MENU_FUNC(eo_http_cb), 0, NULL,
462                        NULL,},
463 #endif
464     {"/File/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
465     {"/File/_Print...", "<control>P", GTK_MENU_FUNC(file_print_cmd_cb),
466                              0, "<StockItem>", GTK_STOCK_PRINT,},
467     {"/File/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
468     {"/File/_Quit", "<control>Q", GTK_MENU_FUNC(file_quit_cmd_cb),
469                              0, "<StockItem>", GTK_STOCK_QUIT,},
470     {"/_Edit", NULL, NULL, 0, "<Branch>", NULL,},
471     {"/Edit/Copy", NULL, NULL, 0, "<Branch>", NULL,},
472     {"/Edit/Copy/As Filter", "<shift><control>C", GTK_MENU_FUNC(match_selected_ptree_cb),
473                        MATCH_SELECTED_REPLACE|MATCH_SELECTED_COPY_ONLY, NULL, NULL,},
474 #if 0
475     /* Un-#if this when we actually implement Cut/Copy/Paste. */
476     {"/Edit/Cut", "<control>X", NULL,
477                              0, "<StockItem>", GTK_STOCK_CUT,},
478     {"/Edit/Copy", "<control>C", NULL,
479                              0, "<StockItem>", GTK_STOCK_COPY,},
480     {"/Edit/Paste", "<control>V", NULL,
481                              0, "<StockItem>", GTK_STOCK_PASTE,},
482 #endif
483     {"/Edit/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
484     {"/Edit/_Find Packet...", "<control>F",
485                              GTK_MENU_FUNC(find_frame_cb), 0, "<StockItem>", GTK_STOCK_FIND,},
486     {"/Edit/Find Ne_xt", "<control>N", GTK_MENU_FUNC(find_next_cb), 0, NULL, NULL,},
487     {"/Edit/Find Pre_vious", "<control>B", GTK_MENU_FUNC(find_previous_cb), 0, NULL, NULL,},
488     {"/Edit/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
489     {"/Edit/_Mark Packet (toggle)", "<control>M", GTK_MENU_FUNC(packet_list_mark_frame_cb),
490                        0, NULL, NULL,},
491     {"/Edit/Find Next Mark", "<shift><control>N", GTK_MENU_FUNC(find_next_mark_cb),
492                        0, NULL, NULL,},
493     {"/Edit/Find Previous Mark", "<shift><control>B", GTK_MENU_FUNC(find_prev_mark_cb),
494                        0, NULL, NULL,},
495     {"/Edit/Mark _All Packets", NULL, GTK_MENU_FUNC(packet_list_mark_all_frames_cb),
496                        0, NULL, NULL,},
497     {"/Edit/_Unmark All Packets", NULL, GTK_MENU_FUNC(packet_list_unmark_all_frames_cb),
498                        0, NULL, NULL,},
499     {"/Edit/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
500     {"/Edit/Set Time Reference (toggle)", "<control>T", GTK_MENU_FUNC(reftime_frame_cb),
501                         REFTIME_TOGGLE, "<StockItem>", WIRESHARK_STOCK_TIME,},
502     {"/Edit/Find Next Reference", NULL, GTK_MENU_FUNC(reftime_frame_cb), REFTIME_FIND_NEXT, NULL, NULL,},
503     {"/Edit/Find Previous Reference", NULL, GTK_MENU_FUNC(reftime_frame_cb), REFTIME_FIND_PREV, NULL, NULL,},
504     {"/Edit/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
505     {"/Edit/_Configuration Profiles...", "<shift><control>A", GTK_MENU_FUNC(profile_dialog_cb), 0, NULL, NULL,},
506     {"/Edit/_Preferences...", "<shift><control>P", GTK_MENU_FUNC(prefs_cb),
507                              0, "<StockItem>", GTK_STOCK_PREFERENCES,},
508     {"/_View", NULL, NULL, 0, "<Branch>", NULL,},
509     {"/View/_Main Toolbar", NULL, GTK_MENU_FUNC(show_hide_cb), SHOW_HIDE_MAIN_TOOLBAR, "<CheckItem>", NULL,},
510     {"/View/_Filter Toolbar", NULL, GTK_MENU_FUNC(show_hide_cb), SHOW_HIDE_FILTER_TOOLBAR, "<CheckItem>", NULL,},
511 #ifdef HAVE_AIRPCAP
512     {"/View/_Wireless Toolbar", NULL, GTK_MENU_FUNC(show_hide_cb), SHOW_HIDE_AIRPCAP_TOOLBAR, "<CheckItem>", NULL,},
513 #endif
514     {"/View/_Statusbar", NULL, GTK_MENU_FUNC(show_hide_cb), SHOW_HIDE_STATUSBAR, "<CheckItem>", NULL,},
515     {"/View/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
516     {"/View/Packet _List", NULL, GTK_MENU_FUNC(show_hide_cb), SHOW_HIDE_PACKET_LIST, "<CheckItem>", NULL,},
517     {"/View/Packet _Details", NULL, GTK_MENU_FUNC(show_hide_cb), SHOW_HIDE_TREE_VIEW, "<CheckItem>", NULL,},
518     {"/View/Packet _Bytes", NULL, GTK_MENU_FUNC(show_hide_cb), SHOW_HIDE_BYTE_VIEW, "<CheckItem>", NULL,},
519     {"/View/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
520     {"/View/_Time Display Format", NULL, NULL, 0, "<Branch>", NULL,},
521     {"/View/Time Display Format/Date and Time of Day:   1970-01-01 01:02:03.123456", NULL, GTK_MENU_FUNC(timestamp_format_cb),
522                         TS_ABSOLUTE_WITH_DATE, "<RadioItem>", NULL,},
523     {"/View/Time Display Format/Time of Day:   01:02:03.123456", NULL, GTK_MENU_FUNC(timestamp_format_cb), 
524                         TS_ABSOLUTE, "/View/Time Display Format/Date and Time of Day:   1970-01-01 01:02:03.123456", NULL,},
525     {"/View/Time Display Format/Seconds Since Beginning of Capture:   123.123456", NULL, GTK_MENU_FUNC(timestamp_format_cb),
526                         TS_RELATIVE, "/View/Time Display Format/Date and Time of Day:   1970-01-01 01:02:03.123456", NULL,},
527     {"/View/Time Display Format/Seconds Since Previous Captured Packet:   1.123456", NULL, GTK_MENU_FUNC(timestamp_format_cb),
528                         TS_DELTA, "/View/Time Display Format/Date and Time of Day:   1970-01-01 01:02:03.123456", NULL,},
529     {"/View/Time Display Format/Seconds Since Previous Displayed Packet:   1.123456", NULL, GTK_MENU_FUNC(timestamp_format_cb),
530                         TS_DELTA_DIS, "/View/Time Display Format/Date and Time of Day:   1970-01-01 01:02:03.123456", NULL,},
531     {"/View/Time Display Format/Seconds Since Epoch (1970-01-01):   1234567890.123456", NULL, GTK_MENU_FUNC(timestamp_format_cb),
532                         TS_EPOCH, "/View/Time Display Format/Date and Time of Day:   1970-01-01 01:02:03.123456", NULL,},
533     {"/View/Time Display Format/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
534     {"/View/Time Display Format/Automatic (File Format Precision)", NULL, GTK_MENU_FUNC(timestamp_precision_cb),
535                         TS_PREC_AUTO, "<RadioItem>", NULL,},
536     {"/View/Time Display Format/Seconds:   0", NULL, GTK_MENU_FUNC(timestamp_precision_cb),
537                         TS_PREC_FIXED_SEC, "/View/Time Display Format/Automatic (File Format Precision)", NULL,},
538     {"/View/Time Display Format/Deciseconds:   0.1", NULL, GTK_MENU_FUNC(timestamp_precision_cb),
539                         TS_PREC_FIXED_DSEC, "/View/Time Display Format/Automatic (File Format Precision)", NULL,},
540     {"/View/Time Display Format/Centiseconds:   0.12", NULL, GTK_MENU_FUNC(timestamp_precision_cb),
541                         TS_PREC_FIXED_CSEC, "/View/Time Display Format/Automatic (File Format Precision)", NULL,},
542     {"/View/Time Display Format/Milliseconds:   0.123", NULL, GTK_MENU_FUNC(timestamp_precision_cb),
543                         TS_PREC_FIXED_MSEC, "/View/Time Display Format/Automatic (File Format Precision)", NULL,},
544     {"/View/Time Display Format/Microseconds:   0.123456", NULL, GTK_MENU_FUNC(timestamp_precision_cb),
545                         TS_PREC_FIXED_USEC, "/View/Time Display Format/Automatic (File Format Precision)", NULL,},
546     {"/View/Time Display Format/Nanoseconds:   0.123456789", NULL, GTK_MENU_FUNC(timestamp_precision_cb),
547                         TS_PREC_FIXED_NSEC, "/View/Time Display Format/Automatic (File Format Precision)", NULL,},
548     {"/View/Name Resol_ution", NULL, NULL, 0, "<Branch>", NULL,},
549     {"/View/Name Resolution/_Resolve Name", NULL, GTK_MENU_FUNC(resolve_name_cb), 0, NULL, NULL,},
550     {"/View/Name Resolution/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
551     {"/View/Name Resolution/Enable for _MAC Layer", NULL, GTK_MENU_FUNC(name_resolution_cb), RESOLV_MAC, "<CheckItem>", NULL,},
552     {"/View/Name Resolution/Enable for _Network Layer", NULL, GTK_MENU_FUNC(name_resolution_cb), RESOLV_NETWORK, "<CheckItem>", NULL,},
553     {"/View/Name Resolution/Enable for _Transport Layer", NULL, GTK_MENU_FUNC(name_resolution_cb), RESOLV_TRANSPORT, "<CheckItem>", NULL,},
554     {"/View/Colorize Packet List", NULL, colorize_cb, 0, "<CheckItem>", NULL,},
555 #ifdef HAVE_LIBPCAP
556     {"/View/Auto Scroll in Li_ve Capture", NULL, GTK_MENU_FUNC(auto_scroll_live_cb), 0, "<CheckItem>", NULL,},
557 #endif
558     {"/View/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
559     {"/View/_Zoom In", "<control>plus", GTK_MENU_FUNC(view_zoom_in_cb),
560                              0, "<StockItem>", GTK_STOCK_ZOOM_IN,},
561     {"/View/Zoom _Out", "<control>minus", GTK_MENU_FUNC(view_zoom_out_cb),
562                              0, "<StockItem>", GTK_STOCK_ZOOM_OUT,},
563     {"/View/_Normal Size", "<control>equal", GTK_MENU_FUNC(view_zoom_100_cb),
564                              0, "<StockItem>", GTK_STOCK_ZOOM_100,},
565     {"/View/Resize All Columns", NULL, GTK_MENU_FUNC(packet_list_resize_columns_cb),
566                        0, "<StockItem>", WIRESHARK_STOCK_RESIZE_COLUMNS,},
567     {"/View/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
568     {"/View/E_xpand Subtrees", "<shift>Right", GTK_MENU_FUNC(expand_tree_cb), 0, NULL, NULL,},
569     {"/View/_Expand All", "<control>Right", GTK_MENU_FUNC(expand_all_cb),
570                        0, NULL, NULL,},
571     {"/View/Collapse _All", "<control>Left", GTK_MENU_FUNC(collapse_all_cb),
572                        0, NULL, NULL,},
573     {"/View/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
574     {"/View/Colorize Conversation", NULL, NULL, 0, "<Branch>",NULL,},
575     {"/View/Colorize Conversation/Color 1", "<control>1",
576                        GTK_MENU_FUNC(colorize_conversation_cb), 1*256, "<StockItem>", WIRESHARK_STOCK_COLOR1,},
577     {"/View/Colorize Conversation/Color 2", "<control>2",
578                        GTK_MENU_FUNC(colorize_conversation_cb), 2*256, "<StockItem>", WIRESHARK_STOCK_COLOR2,},
579     {"/View/Colorize Conversation/Color 3", "<control>3",
580                        GTK_MENU_FUNC(colorize_conversation_cb), 3*256, "<StockItem>", WIRESHARK_STOCK_COLOR3,},
581     {"/View/Colorize Conversation/Color 4", "<control>4",
582                        GTK_MENU_FUNC(colorize_conversation_cb), 4*256, "<StockItem>", WIRESHARK_STOCK_COLOR4,},
583     {"/View/Colorize Conversation/Color 5", "<control>5",
584                        GTK_MENU_FUNC(colorize_conversation_cb), 5*256, "<StockItem>", WIRESHARK_STOCK_COLOR5,},
585     {"/View/Colorize Conversation/Color 6", "<control>6",
586                        GTK_MENU_FUNC(colorize_conversation_cb), 6*256, "<StockItem>", WIRESHARK_STOCK_COLOR6,},
587     {"/View/Colorize Conversation/Color 7", "<control>7",
588                        GTK_MENU_FUNC(colorize_conversation_cb), 7*256, "<StockItem>", WIRESHARK_STOCK_COLOR7,},
589     {"/View/Colorize Conversation/Color 8", "<control>8",
590                        GTK_MENU_FUNC(colorize_conversation_cb), 8*256, "<StockItem>", WIRESHARK_STOCK_COLOR8,},
591     {"/View/Colorize Conversation/Color 9", "<control>9",
592                        GTK_MENU_FUNC(colorize_conversation_cb), 9*256, "<StockItem>", WIRESHARK_STOCK_COLOR9,},
593     {"/View/Colorize Conversation/Color 10", "<control>0",
594                        GTK_MENU_FUNC(colorize_conversation_cb), 10*256, "<StockItem>", WIRESHARK_STOCK_COLOR0,},
595     {"/View/Colorize Conversation/<separator>", NULL,
596                        NULL, 0, "<Separator>",NULL,},
597     {"/View/Colorize Conversation/New Coloring Rule...", NULL,
598                        GTK_MENU_FUNC(colorize_conversation_cb), 0, "<StockItem>", GTK_STOCK_SELECT_COLOR,},
599     {"/View/Reset Coloring 1-10", "<control>space",
600                        GTK_MENU_FUNC(colorize_conversation_cb), 255*256, NULL, NULL,},
601     {"/View/_Coloring Rules...", NULL, color_display_cb,
602                        0, "<StockItem>", GTK_STOCK_SELECT_COLOR,},
603     {"/View/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
604
605
606     {"/View/Show Packet in New _Window", NULL,
607                        GTK_MENU_FUNC(new_window_cb), 0, NULL, NULL,},
608     {"/View/_Reload", "<control>R", GTK_MENU_FUNC(file_reload_cmd_cb),
609                              0, "<StockItem>", GTK_STOCK_REFRESH,},
610     {"/_Go", NULL, NULL, 0, "<Branch>", NULL,},
611     {"/Go/_Back", "<alt>Left",
612                              GTK_MENU_FUNC(history_back_cb), 0, "<StockItem>", GTK_STOCK_GO_BACK,},
613     {"/Go/_Forward", "<alt>Right",
614                              GTK_MENU_FUNC(history_forward_cb), 0, "<StockItem>", GTK_STOCK_GO_FORWARD,},
615     {"/Go/_Go to Packet...", "<control>G",
616                              GTK_MENU_FUNC(goto_frame_cb), 0, "<StockItem>", GTK_STOCK_JUMP_TO,},
617     {"/Go/Go to _Corresponding Packet", NULL, GTK_MENU_FUNC(goto_framenum_cb),
618                        0, NULL, NULL,},
619     {"/Go/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
620     {"/Go/Previous Packet", "<control>Up",
621                              GTK_MENU_FUNC(packet_list_prev), 0, "<StockItem>", GTK_STOCK_GO_UP,},
622     {"/Go/Next Packet", "<control>Down",
623                              GTK_MENU_FUNC(packet_list_next), 0, "<StockItem>", GTK_STOCK_GO_DOWN,},
624     {"/Go/F_irst Packet", NULL,
625                              GTK_MENU_FUNC(goto_top_frame_cb), 0, "<StockItem>", GTK_STOCK_GOTO_TOP,},
626     {"/Go/_Last Packet", NULL,
627                              GTK_MENU_FUNC(goto_bottom_frame_cb), 0, "<StockItem>", GTK_STOCK_GOTO_BOTTOM,},
628 #ifdef HAVE_LIBPCAP
629     {"/_Capture", NULL, NULL, 0, "<Branch>", NULL,},
630     {"/Capture/_Interfaces...", NULL,
631                              GTK_MENU_FUNC(capture_if_cb), 0, "<StockItem>", WIRESHARK_STOCK_CAPTURE_INTERFACES,},
632     {"/Capture/_Options...", "<control>K",
633                              GTK_MENU_FUNC(capture_prep_cb), 0, "<StockItem>", WIRESHARK_STOCK_CAPTURE_OPTIONS,},
634     {"/Capture/_Start", NULL,
635                              GTK_MENU_FUNC(capture_start_cb), 0, "<StockItem>", WIRESHARK_STOCK_CAPTURE_START,},
636     {"/Capture/S_top", "<control>E", GTK_MENU_FUNC(capture_stop_cb),
637                              0, "<StockItem>", WIRESHARK_STOCK_CAPTURE_STOP,},
638     {"/Capture/_Restart", NULL, GTK_MENU_FUNC(capture_restart_cb),
639                              0, "<StockItem>", WIRESHARK_STOCK_CAPTURE_RESTART,},
640     {"/Capture/Capture _Filters...", NULL, GTK_MENU_FUNC(cfilter_dialog_cb),
641                        0, "<StockItem>", WIRESHARK_STOCK_CAPTURE_FILTER,},
642 #endif /* HAVE_LIBPCAP */
643     {"/_Analyze", NULL, NULL, 0, "<Branch>", NULL,},
644     {"/Analyze/_Display Filters...", NULL, GTK_MENU_FUNC(dfilter_dialog_cb),
645                        0, "<StockItem>", WIRESHARK_STOCK_DISPLAY_FILTER,},
646     {"/Analyze/Display Filter _Macros...", NULL, GTK_MENU_FUNC(macros_dialog_cb), 0, NULL, NULL,},
647     {"/Analyze/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
648     {"/Analyze/Appl_y as Filter", NULL, NULL, 0, "<Branch>", NULL,},
649     {"/Analyze/Apply as Filter/_Selected", NULL, GTK_MENU_FUNC(match_selected_ptree_cb),
650                        MATCH_SELECTED_REPLACE|MATCH_SELECTED_APPLY_NOW, NULL, NULL,},
651     {"/Analyze/Apply as Filter/_Not Selected", NULL, GTK_MENU_FUNC(match_selected_ptree_cb),
652                        MATCH_SELECTED_NOT|MATCH_SELECTED_APPLY_NOW, NULL, NULL,},
653     {"/Analyze/Apply as Filter/... _and Selected", NULL, GTK_MENU_FUNC(match_selected_ptree_cb),
654                        MATCH_SELECTED_AND|MATCH_SELECTED_APPLY_NOW, NULL, NULL,},
655     {"/Analyze/Apply as Filter/... _or Selected", NULL, GTK_MENU_FUNC(match_selected_ptree_cb),
656                        MATCH_SELECTED_OR|MATCH_SELECTED_APPLY_NOW, NULL, NULL,},
657     {"/Analyze/Apply as Filter/... a_nd not Selected", NULL, GTK_MENU_FUNC(match_selected_ptree_cb),
658                        MATCH_SELECTED_AND_NOT|MATCH_SELECTED_APPLY_NOW, NULL, NULL,},
659     {"/Analyze/Apply as Filter/... o_r not Selected", NULL, GTK_MENU_FUNC(match_selected_ptree_cb),
660                        MATCH_SELECTED_OR_NOT|MATCH_SELECTED_APPLY_NOW, NULL, NULL,},
661     {"/Analyze/_Prepare a Filter", NULL, NULL, 0, "<Branch>", NULL,},
662     {"/Analyze/Prepare a Filter/_Selected", NULL, GTK_MENU_FUNC(match_selected_ptree_cb),
663                        MATCH_SELECTED_REPLACE, NULL, NULL,},
664     {"/Analyze/Prepare a Filter/_Not Selected", NULL, GTK_MENU_FUNC(match_selected_ptree_cb),
665                        MATCH_SELECTED_NOT, NULL, NULL,},
666     {"/Analyze/Prepare a Filter/... _and Selected", NULL, GTK_MENU_FUNC(match_selected_ptree_cb),
667                        MATCH_SELECTED_AND, NULL, NULL,},
668     {"/Analyze/Prepare a Filter/... _or Selected", NULL, GTK_MENU_FUNC(match_selected_ptree_cb),
669                        MATCH_SELECTED_OR, NULL, NULL,},
670     {"/Analyze/Prepare a Filter/... a_nd not Selected", NULL, GTK_MENU_FUNC(match_selected_ptree_cb),
671                        MATCH_SELECTED_AND_NOT, NULL, NULL,},
672     {"/Analyze/Prepare a Filter/... o_r not Selected", NULL, GTK_MENU_FUNC(match_selected_ptree_cb),
673                        MATCH_SELECTED_OR_NOT, NULL, NULL,},
674     {"/Analyze/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
675     {"/Analyze/_Enabled Protocols...", "<shift><control>R", GTK_MENU_FUNC(proto_cb), 
676                        0, "<StockItem>", WIRESHARK_STOCK_CHECKBOX,},
677     {"/Analyze/Decode _As...", NULL, GTK_MENU_FUNC(decode_as_cb),
678                        0, "<StockItem>", WIRESHARK_STOCK_DECODE_AS,},
679     {"/Analyze/_User Specified Decodes...", NULL,
680                        GTK_MENU_FUNC(decode_show_cb), 0, "<StockItem>", WIRESHARK_STOCK_DECODE_AS,},
681     {"/Analyze/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
682     {"/Analyze/_Follow TCP Stream", NULL,
683                        GTK_MENU_FUNC(follow_tcp_stream_cb), 0, NULL, NULL,},
684     {"/Analyze/_Follow UDP Stream", NULL,
685                        GTK_MENU_FUNC(follow_udp_stream_cb), 0, NULL, NULL,},
686     {"/Analyze/_Follow SSL Stream", NULL,
687                        GTK_MENU_FUNC(follow_ssl_stream_cb), 0, NULL, NULL,},
688     {"/_Statistics", NULL, NULL, 0, "<Branch>", NULL,},
689     {"/Statistics/_Summary", NULL, GTK_MENU_FUNC(summary_open_cb), 0, "<StockItem>", GTK_STOCK_PROPERTIES,},
690     {"/Statistics/_Protocol Hierarchy", NULL,
691                        GTK_MENU_FUNC(proto_hier_stats_cb), 0, NULL, NULL,},
692     {"/Statistics/Conversations", NULL,
693                        GTK_MENU_FUNC(init_conversation_notebook_cb), 0, "<StockItem>", WIRESHARK_STOCK_CONVERSATIONS,},
694     {"/Statistics/Endpoints", NULL,
695                        GTK_MENU_FUNC(init_hostlist_notebook_cb), 0, "<StockItem>", WIRESHARK_STOCK_ENDPOINTS,},
696     {"/_Tools", NULL, NULL, 0, "<Branch>", NULL,},
697     {"/Tools/Firewall ACL Rules", NULL,
698                        firewall_rule_cb, 0, NULL, NULL,},
699     {"/_Help", NULL, NULL, 0, "<Branch>", NULL,},
700     {"/Help/_Contents", "F1", GTK_MENU_FUNC(topic_menu_cb), HELP_CONTENT, "<StockItem>", GTK_STOCK_HELP,},
701     {"/Help/_Supported Protocols", NULL, GTK_MENU_FUNC(supported_cb), 0, NULL, NULL,},
702     {"/Help/Manual Pages", NULL, NULL, 0, "<Branch>", NULL,},
703     {"/Help/Manual Pages/Wireshark", NULL, GTK_MENU_FUNC(topic_menu_cb), LOCALPAGE_MAN_WIRESHARK, NULL, NULL,},
704     {"/Help/Manual Pages/Wireshark Filter", NULL, GTK_MENU_FUNC(topic_menu_cb), LOCALPAGE_MAN_WIRESHARK_FILTER, NULL, NULL,},
705     {"/Help/Manual Pages/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
706     {"/Help/Manual Pages/TShark", NULL, GTK_MENU_FUNC(topic_menu_cb), LOCALPAGE_MAN_TSHARK, NULL, NULL,},
707     {"/Help/Manual Pages/RawShark", NULL, GTK_MENU_FUNC(topic_menu_cb), LOCALPAGE_MAN_RAWSHARK, NULL, NULL,},
708     {"/Help/Manual Pages/Dumpcap", NULL, GTK_MENU_FUNC(topic_menu_cb), LOCALPAGE_MAN_DUMPCAP, NULL, NULL,},
709     {"/Help/Manual Pages/Mergecap", NULL, GTK_MENU_FUNC(topic_menu_cb), LOCALPAGE_MAN_MERGECAP, NULL, NULL,},
710     {"/Help/Manual Pages/Editcap", NULL, GTK_MENU_FUNC(topic_menu_cb), LOCALPAGE_MAN_EDITCAP, NULL, NULL,},
711     {"/Help/Manual Pages/Text2pcap", NULL, GTK_MENU_FUNC(topic_menu_cb), LOCALPAGE_MAN_TEXT2PCAP, NULL, NULL,},
712     {"/Help/Wireshark Online", NULL, NULL, 0, "<Branch>", NULL,},
713     {"/Help/Wireshark Online/Home Page", NULL, GTK_MENU_FUNC(topic_menu_cb), ONLINEPAGE_HOME, "<StockItem>", GTK_STOCK_HOME,},
714     {"/Help/Wireshark Online/Wiki", NULL, GTK_MENU_FUNC(topic_menu_cb), ONLINEPAGE_WIKI, "<StockItem>", WIRESHARK_STOCK_WIKI,},
715     {"/Help/Wireshark Online/User's Guide", NULL, GTK_MENU_FUNC(topic_menu_cb), ONLINEPAGE_USERGUIDE, "<StockItem>", WIRESHARK_STOCK_WEB_SUPPORT,},
716     {"/Help/Wireshark Online/FAQ's", NULL, GTK_MENU_FUNC(topic_menu_cb), ONLINEPAGE_FAQ, NULL, NULL,},
717     {"/Help/Wireshark Online/Downloads", NULL, GTK_MENU_FUNC(topic_menu_cb), ONLINEPAGE_DOWNLOAD, NULL, NULL,},
718     {"/Help/Wireshark Online/Example Files", NULL, GTK_MENU_FUNC(topic_menu_cb), ONLINEPAGE_SAMPLE_FILES, NULL, NULL,},
719     {"/Help/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
720     {"/Help/_About Wireshark", NULL, GTK_MENU_FUNC(about_wireshark_cb),
721                        0, "<StockItem>", WIRESHARK_STOCK_ABOUT}
722 };
723
724
725 /* calculate the number of menu_items */
726 static int nmenu_items = sizeof(menu_items) / sizeof(menu_items[0]);
727
728 /* packet list popup */
729 static GtkItemFactoryEntry packet_list_menu_items[] =
730 {
731     {"/Mark Packet (toggle)", NULL, GTK_MENU_FUNC(packet_list_mark_frame_cb), 0, NULL, NULL,},
732     {"/Set Time Reference (toggle)", NULL, GTK_MENU_FUNC(reftime_frame_cb), REFTIME_TOGGLE, "<StockItem>", WIRESHARK_STOCK_TIME,},
733
734     {"/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
735
736     {"/Apply as Filter", NULL, NULL, 0, "<Branch>", NULL,},
737     {"/Apply as Filter/_Selected", NULL, GTK_MENU_FUNC(match_selected_plist_cb),
738                        MATCH_SELECTED_REPLACE|MATCH_SELECTED_APPLY_NOW, NULL, NULL,},
739     {"/Apply as Filter/_Not Selected", NULL, GTK_MENU_FUNC(match_selected_plist_cb),
740                        MATCH_SELECTED_NOT|MATCH_SELECTED_APPLY_NOW, NULL, NULL,},
741     {"/Apply as Filter/... _and Selected", NULL, GTK_MENU_FUNC(match_selected_plist_cb),
742                        MATCH_SELECTED_AND|MATCH_SELECTED_APPLY_NOW, NULL, NULL,},
743     {"/Apply as Filter/... _or Selected", NULL, GTK_MENU_FUNC(match_selected_plist_cb),
744                        MATCH_SELECTED_OR|MATCH_SELECTED_APPLY_NOW, NULL, NULL,},
745     {"/Apply as Filter/... a_nd not Selected", NULL, GTK_MENU_FUNC(match_selected_plist_cb),
746                        MATCH_SELECTED_AND_NOT|MATCH_SELECTED_APPLY_NOW, NULL, NULL,},
747     {"/Apply as Filter/... o_r not Selected", NULL, GTK_MENU_FUNC(match_selected_plist_cb),
748                        MATCH_SELECTED_OR_NOT|MATCH_SELECTED_APPLY_NOW, NULL, NULL,},
749
750     {"/Prepare a Filter", NULL, NULL, 0, "<Branch>", NULL,},
751     {"/Prepare a Filter/_Selected", NULL, GTK_MENU_FUNC(match_selected_plist_cb),
752                        MATCH_SELECTED_REPLACE, NULL, NULL,},
753     {"/Prepare a Filter/_Not Selected", NULL, GTK_MENU_FUNC(match_selected_plist_cb),
754                        MATCH_SELECTED_NOT, NULL, NULL,},
755     {"/Prepare a Filter/... _and Selected", NULL, GTK_MENU_FUNC(match_selected_plist_cb),
756                        MATCH_SELECTED_AND, NULL, NULL,},
757     {"/Prepare a Filter/... _or Selected", NULL, GTK_MENU_FUNC(match_selected_plist_cb),
758                        MATCH_SELECTED_OR, NULL, NULL,},
759     {"/Prepare a Filter/... a_nd not Selected", NULL, GTK_MENU_FUNC(match_selected_plist_cb),
760                        MATCH_SELECTED_AND_NOT, NULL, NULL,},
761     {"/Prepare a Filter/... o_r not Selected", NULL, GTK_MENU_FUNC(match_selected_plist_cb),
762                        MATCH_SELECTED_OR_NOT, NULL, NULL,},
763
764     {"/Conversation Filter", NULL, NULL, 0, "<Branch>",NULL,},
765     {"/Conversation Filter/Ethernet", NULL, GTK_MENU_FUNC(conversation_cb),
766                        CONV_ETHER, NULL, NULL,},
767     {"/Conversation Filter/IP", NULL, GTK_MENU_FUNC(conversation_cb),
768                        CONV_IP, NULL, NULL,},
769     {"/Conversation Filter/TCP", NULL, GTK_MENU_FUNC(conversation_cb),
770                        CONV_TCP, NULL, NULL,},
771     {"/Conversation Filter/UDP", NULL, GTK_MENU_FUNC(conversation_cb),
772                        CONV_UDP, NULL, NULL,},
773     {"/Conversation Filter/PN-CBA Server", NULL, GTK_MENU_FUNC(conversation_cb),
774                        CONV_CBA, NULL, NULL,},
775
776     {"/Colorize Conversation", NULL, NULL, 0, "<Branch>",NULL,},
777     {"/Colorize Conversation/Ethernet", NULL, NULL, 0, "<Branch>",NULL,},
778     {"/Colorize Conversation/Ethernet/Color 1", NULL,
779                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_ETHER+1*256, "<StockItem>", WIRESHARK_STOCK_COLOR1,},
780     {"/Colorize Conversation/Ethernet/Color 2", NULL,
781                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_ETHER+2*256, "<StockItem>", WIRESHARK_STOCK_COLOR2,},
782     {"/Colorize Conversation/Ethernet/Color 3", NULL,
783                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_ETHER+3*256, "<StockItem>", WIRESHARK_STOCK_COLOR3,},
784     {"/Colorize Conversation/Ethernet/Color 4", NULL,
785                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_ETHER+4*256, "<StockItem>", WIRESHARK_STOCK_COLOR4,},
786     {"/Colorize Conversation/Ethernet/Color 5", NULL,
787                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_ETHER+5*256, "<StockItem>", WIRESHARK_STOCK_COLOR5,},
788     {"/Colorize Conversation/Ethernet/Color 6", NULL,
789                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_ETHER+6*256, "<StockItem>", WIRESHARK_STOCK_COLOR6,},
790     {"/Colorize Conversation/Ethernet/Color 7", NULL,
791                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_ETHER+7*256, "<StockItem>", WIRESHARK_STOCK_COLOR7,},
792     {"/Colorize Conversation/Ethernet/Color 8", NULL,
793                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_ETHER+8*256, "<StockItem>", WIRESHARK_STOCK_COLOR8,},
794     {"/Colorize Conversation/Ethernet/Color 9", NULL,
795                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_ETHER+9*256, "<StockItem>", WIRESHARK_STOCK_COLOR9,},
796     {"/Colorize Conversation/Ethernet/Color 10", NULL,
797                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_ETHER+10*256, "<StockItem>", WIRESHARK_STOCK_COLOR0,},
798     {"/Colorize Conversation/Ethernet/<separator>", NULL,
799                        NULL, 0, "<Separator>",NULL,},
800     {"/Colorize Conversation/Ethernet/New Coloring Rule...", NULL,
801                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_ETHER, "<StockItem>", GTK_STOCK_SELECT_COLOR,},
802     {"/Colorize Conversation/IP", NULL, NULL, 0, "<Branch>",NULL,},
803     {"/Colorize Conversation/IP/Color 1", NULL,
804                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_IP+1*256, "<StockItem>", WIRESHARK_STOCK_COLOR1,},
805     {"/Colorize Conversation/IP/Color 2", NULL,
806                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_IP+2*256, "<StockItem>", WIRESHARK_STOCK_COLOR2,},
807     {"/Colorize Conversation/IP/Color 3", NULL,
808                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_IP+3*256, "<StockItem>", WIRESHARK_STOCK_COLOR3,},
809     {"/Colorize Conversation/IP/Color 4", NULL,
810                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_IP+4*256, "<StockItem>", WIRESHARK_STOCK_COLOR4,},
811     {"/Colorize Conversation/IP/Color 5", NULL,
812                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_IP+5*256, "<StockItem>", WIRESHARK_STOCK_COLOR5,},
813     {"/Colorize Conversation/IP/Color 6", NULL,
814                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_IP+6*256, "<StockItem>", WIRESHARK_STOCK_COLOR6,},
815     {"/Colorize Conversation/IP/Color 7", NULL,
816                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_IP+7*256, "<StockItem>", WIRESHARK_STOCK_COLOR7,},
817     {"/Colorize Conversation/IP/Color 8", NULL,
818                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_IP+8*256, "<StockItem>", WIRESHARK_STOCK_COLOR8,},
819     {"/Colorize Conversation/IP/Color 9", NULL,
820                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_IP+9*256, "<StockItem>", WIRESHARK_STOCK_COLOR9,},
821     {"/Colorize Conversation/IP/Color 10", NULL,
822                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_IP+10*256, "<StockItem>", WIRESHARK_STOCK_COLOR0,},
823     {"/Colorize Conversation/IP/<separator>", NULL,
824                        NULL, 0, "<Separator>",NULL,},
825     {"/Colorize Conversation/IP/New Coloring Rule...", NULL,
826                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_IP, "<StockItem>", GTK_STOCK_SELECT_COLOR,},
827     {"/Colorize Conversation/TCP", NULL, NULL, 0, "<Branch>",NULL,},
828     {"/Colorize Conversation/TCP/Color 1", NULL,
829                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_TCP+1*256, "<StockItem>", WIRESHARK_STOCK_COLOR1,},
830     {"/Colorize Conversation/TCP/Color 2", NULL,
831                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_TCP+2*256, "<StockItem>", WIRESHARK_STOCK_COLOR2,},
832     {"/Colorize Conversation/TCP/Color 3", NULL,
833                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_TCP+3*256, "<StockItem>", WIRESHARK_STOCK_COLOR3,},
834     {"/Colorize Conversation/TCP/Color 4", NULL,
835                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_TCP+4*256, "<StockItem>", WIRESHARK_STOCK_COLOR4,},
836     {"/Colorize Conversation/TCP/Color 5", NULL,
837                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_TCP+5*256, "<StockItem>", WIRESHARK_STOCK_COLOR5,},
838     {"/Colorize Conversation/TCP/Color 6", NULL,
839                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_TCP+6*256, "<StockItem>", WIRESHARK_STOCK_COLOR6,},
840     {"/Colorize Conversation/TCP/Color 7", NULL,
841                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_TCP+7*256, "<StockItem>", WIRESHARK_STOCK_COLOR7,},
842     {"/Colorize Conversation/TCP/Color 8", NULL,
843                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_TCP+8*256, "<StockItem>", WIRESHARK_STOCK_COLOR8,},
844     {"/Colorize Conversation/TCP/Color 9", NULL,
845                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_TCP+9*256, "<StockItem>", WIRESHARK_STOCK_COLOR9,},
846     {"/Colorize Conversation/TCP/Color 10", NULL,
847                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_TCP+10*256, "<StockItem>", WIRESHARK_STOCK_COLOR0,},
848     {"/Colorize Conversation/TCP/<separator>", NULL,
849                        NULL, 0, "<Separator>",NULL,},
850     {"/Colorize Conversation/TCP/New Coloring Rule...", NULL,
851                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_TCP, "<StockItem>", GTK_STOCK_SELECT_COLOR,},
852     {"/Colorize Conversation/UDP", NULL, NULL, 0, "<Branch>",NULL,},
853     {"/Colorize Conversation/UDP/Color 1", NULL,
854                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_UDP+1*256, "<StockItem>", WIRESHARK_STOCK_COLOR1,},
855     {"/Colorize Conversation/UDP/Color 2", NULL,
856                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_UDP+2*256, "<StockItem>", WIRESHARK_STOCK_COLOR2,},
857     {"/Colorize Conversation/UDP/Color 3", NULL,
858                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_UDP+3*256, "<StockItem>", WIRESHARK_STOCK_COLOR3,},
859     {"/Colorize Conversation/UDP/Color 4", NULL,
860                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_UDP+4*256, "<StockItem>", WIRESHARK_STOCK_COLOR4,},
861     {"/Colorize Conversation/UDP/Color 5", NULL,
862                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_UDP+5*256, "<StockItem>", WIRESHARK_STOCK_COLOR5,},
863     {"/Colorize Conversation/UDP/Color 6", NULL,
864                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_UDP+6*256, "<StockItem>", WIRESHARK_STOCK_COLOR6,},
865     {"/Colorize Conversation/UDP/Color 7", NULL,
866                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_UDP+7*256, "<StockItem>", WIRESHARK_STOCK_COLOR7,},
867     {"/Colorize Conversation/UDP/Color 8", NULL,
868                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_UDP+8*256, "<StockItem>", WIRESHARK_STOCK_COLOR8,},
869     {"/Colorize Conversation/UDP/Color 9", NULL,
870                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_UDP+9*256, "<StockItem>", WIRESHARK_STOCK_COLOR9,},
871     {"/Colorize Conversation/UDP/Color 10", NULL,
872                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_UDP+10*256, "<StockItem>", WIRESHARK_STOCK_COLOR0,},
873     {"/Colorize Conversation/UDP/<separator>", NULL,
874                        NULL, 0, "<Separator>",NULL,},
875     {"/Colorize Conversation/UDP/New Coloring Rule...", NULL,
876                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_UDP, "<StockItem>", GTK_STOCK_SELECT_COLOR,},
877     {"/Colorize Conversation/PN-CBA Server", NULL, NULL, 0, "<Branch>",NULL,},
878     {"/Colorize Conversation/PN-CBA Server/Color 1", NULL,
879                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_CBA+1*256, "<StockItem>", WIRESHARK_STOCK_COLOR1,},
880     {"/Colorize Conversation/PN-CBA Server/Color 2", NULL,
881                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_CBA+2*256, "<StockItem>", WIRESHARK_STOCK_COLOR2,},
882     {"/Colorize Conversation/PN-CBA Server/Color 3", NULL,
883                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_CBA+3*256, "<StockItem>", WIRESHARK_STOCK_COLOR3,},
884     {"/Colorize Conversation/PN-CBA Server/Color 4", NULL,
885                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_CBA+4*256, "<StockItem>", WIRESHARK_STOCK_COLOR4,},
886     {"/Colorize Conversation/PN-CBA Server/Color 5", NULL,
887                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_CBA+5*256, "<StockItem>", WIRESHARK_STOCK_COLOR5,},
888     {"/Colorize Conversation/PN-CBA Server/Color 6", NULL,
889                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_CBA+6*256, "<StockItem>", WIRESHARK_STOCK_COLOR6,},
890     {"/Colorize Conversation/PN-CBA Server/Color 7", NULL,
891                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_CBA+7*256, "<StockItem>", WIRESHARK_STOCK_COLOR7,},
892     {"/Colorize Conversation/PN-CBA Server/Color 8", NULL,
893                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_CBA+8*256, "<StockItem>", WIRESHARK_STOCK_COLOR8,},
894     {"/Colorize Conversation/PN-CBA Server/Color 9", NULL,
895                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_CBA+9*256, "<StockItem>", WIRESHARK_STOCK_COLOR9,},
896     {"/Colorize Conversation/PN-CBA Server/Color 10", NULL,
897                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_CBA+10*256, "<StockItem>", WIRESHARK_STOCK_COLOR0,},
898     {"/Colorize Conversation/PN-CBA Server/<separator>", NULL,
899                        NULL, 0, "<Separator>",NULL,},
900     {"/Colorize Conversation/PN-CBA Server/New Coloring Rule...", NULL,
901                        GTK_MENU_FUNC(colorize_conversation_cb), CONV_CBA, "<StockItem>", GTK_STOCK_SELECT_COLOR,},
902
903     {"/SCTP", NULL, NULL, 0, "<Branch>",NULL,},
904     {"/SCTP/Analyse this Association", NULL, GTK_MENU_FUNC(sctp_analyse_start),
905                        0, NULL,NULL,},
906     {"/SCTP/Prepare Filter for this Association", NULL, (sctp_set_assoc_filter),
907                        0, NULL,NULL,},
908
909     {"/Follow TCP Stream", NULL, (follow_tcp_stream_cb),
910                        0, NULL, NULL,},
911     {"/Follow UDP Stream", NULL, (follow_udp_stream_cb),
912                        0, NULL, NULL,},
913     {"/Follow SSL Stream", NULL, (follow_ssl_stream_cb),
914                        0, NULL, NULL,},
915
916     {"/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
917
918     {"/Copy", NULL, NULL, 0, "<Branch>", NULL,},
919     {"/Copy/Summary (Text)", NULL, GTK_MENU_FUNC(packet_list_copy_summary_cb), CS_TEXT, NULL, NULL,},
920     {"/Copy/Summary (CSV)", NULL, GTK_MENU_FUNC(packet_list_copy_summary_cb), CS_CSV, NULL, NULL,},
921     {"/Copy/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
922     {"/Copy/As Filter", NULL, GTK_MENU_FUNC(match_selected_plist_cb),
923                        MATCH_SELECTED_REPLACE|MATCH_SELECTED_COPY_ONLY, NULL, NULL,},
924     {"/Copy/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
925     {"/Copy/Bytes (Offset Hex Text)", NULL, GTK_MENU_FUNC(copy_hex_cb), CD_ALLINFO, NULL, NULL,},
926     {"/Copy/Bytes (Offset Hex)", NULL, GTK_MENU_FUNC(copy_hex_cb), CD_HEXCOLUMNS, NULL, NULL,},
927     {"/Copy/Bytes (Printable Text Only)", NULL, GTK_MENU_FUNC(copy_hex_cb), CD_TEXTONLY, NULL, NULL,},
928     {"/Copy/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
929     {"/Copy/Bytes (Hex Stream)", NULL, GTK_MENU_FUNC(copy_hex_cb), CD_HEX, NULL, NULL,},
930     {"/Copy/Bytes (Binary Stream)", NULL, GTK_MENU_FUNC(copy_hex_cb), CD_BINARY, NULL, NULL,},
931
932     {"/Export Selected Packet Bytes...", NULL, GTK_MENU_FUNC(savehex_cb),
933                        0, NULL, NULL,},
934
935     {"/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
936
937     {"/Decode As...", NULL, GTK_MENU_FUNC(decode_as_cb), 0, "<StockItem>", WIRESHARK_STOCK_DECODE_AS,},
938     {"/Print...", NULL, GTK_MENU_FUNC(file_print_selected_cmd_cb), 0, "<StockItem>", GTK_STOCK_PRINT,},
939     {"/Show Packet in New Window", NULL, GTK_MENU_FUNC(new_window_cb),
940                        0, NULL, NULL}
941 };
942
943 static GtkItemFactoryEntry tree_view_menu_items[] =
944 {
945
946     {"/Expand Subtrees", NULL, GTK_MENU_FUNC(expand_tree_cb), 0, NULL, NULL,},
947     {"/Expand All", NULL, GTK_MENU_FUNC(expand_all_cb), 0, NULL, NULL,},
948     {"/Collapse All", NULL, GTK_MENU_FUNC(collapse_all_cb), 0, NULL, NULL,},
949
950     {"/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
951
952     {"/Apply as Filter", NULL, NULL, 0, "<Branch>", NULL,},
953     {"/Apply as Filter/_Selected", NULL, GTK_MENU_FUNC(match_selected_ptree_cb),
954                        MATCH_SELECTED_REPLACE|MATCH_SELECTED_APPLY_NOW, NULL, NULL,},
955     {"/Apply as Filter/_Not Selected", NULL, GTK_MENU_FUNC(match_selected_ptree_cb),
956                        MATCH_SELECTED_NOT|MATCH_SELECTED_APPLY_NOW, NULL, NULL,},
957     {"/Apply as Filter/... _and Selected", NULL, GTK_MENU_FUNC(match_selected_ptree_cb),
958                        MATCH_SELECTED_AND|MATCH_SELECTED_APPLY_NOW, NULL, NULL,},
959     {"/Apply as Filter/... _or Selected", NULL, GTK_MENU_FUNC(match_selected_ptree_cb),
960                        MATCH_SELECTED_OR|MATCH_SELECTED_APPLY_NOW, NULL, NULL,},
961     {"/Apply as Filter/... a_nd not Selected", NULL, GTK_MENU_FUNC(match_selected_ptree_cb),
962                        MATCH_SELECTED_AND_NOT|MATCH_SELECTED_APPLY_NOW, NULL, NULL,},
963     {"/Apply as Filter/... o_r not Selected", NULL, GTK_MENU_FUNC(match_selected_ptree_cb),
964                        MATCH_SELECTED_OR_NOT|MATCH_SELECTED_APPLY_NOW, NULL, NULL,},
965
966     {"/Prepare a Filter", NULL, NULL, 0, "<Branch>", NULL,},
967     {"/Prepare a Filter/_Selected", NULL, GTK_MENU_FUNC(match_selected_ptree_cb),
968                        MATCH_SELECTED_REPLACE, NULL, NULL,},
969     {"/Prepare a Filter/_Not Selected", NULL, GTK_MENU_FUNC(match_selected_ptree_cb),
970                        MATCH_SELECTED_NOT, NULL, NULL,},
971     {"/Prepare a Filter/... _and Selected", NULL, GTK_MENU_FUNC(match_selected_ptree_cb),
972                        MATCH_SELECTED_AND, NULL, NULL,},
973     {"/Prepare a Filter/... _or Selected", NULL, GTK_MENU_FUNC(match_selected_ptree_cb),
974                        MATCH_SELECTED_OR, NULL, NULL,},
975     {"/Prepare a Filter/... a_nd not Selected", NULL, GTK_MENU_FUNC(match_selected_ptree_cb),
976                        MATCH_SELECTED_AND_NOT, NULL, NULL,},
977     {"/Prepare a Filter/... o_r not Selected", NULL, GTK_MENU_FUNC(match_selected_ptree_cb),
978                        MATCH_SELECTED_OR_NOT, NULL, NULL,},
979
980     {"/Colorize with Filter", NULL, NULL, 0, "<Branch>", NULL,},
981     {"/Colorize with Filter/Color 1", NULL, GTK_MENU_FUNC(colorize_selected_ptree_cb), 1, "<StockItem>", WIRESHARK_STOCK_COLOR1,},
982     {"/Colorize with Filter/Color 2", NULL, GTK_MENU_FUNC(colorize_selected_ptree_cb), 2, "<StockItem>", WIRESHARK_STOCK_COLOR2,},
983     {"/Colorize with Filter/Color 3", NULL, GTK_MENU_FUNC(colorize_selected_ptree_cb), 3, "<StockItem>", WIRESHARK_STOCK_COLOR3,},
984     {"/Colorize with Filter/Color 4", NULL, GTK_MENU_FUNC(colorize_selected_ptree_cb), 4, "<StockItem>", WIRESHARK_STOCK_COLOR4,},
985     {"/Colorize with Filter/Color 5", NULL, GTK_MENU_FUNC(colorize_selected_ptree_cb), 5, "<StockItem>", WIRESHARK_STOCK_COLOR5,},
986     {"/Colorize with Filter/Color 6", NULL, GTK_MENU_FUNC(colorize_selected_ptree_cb), 6, "<StockItem>", WIRESHARK_STOCK_COLOR6,},
987     {"/Colorize with Filter/Color 7", NULL, GTK_MENU_FUNC(colorize_selected_ptree_cb), 7, "<StockItem>", WIRESHARK_STOCK_COLOR7,},
988     {"/Colorize with Filter/Color 8", NULL, GTK_MENU_FUNC(colorize_selected_ptree_cb), 8, "<StockItem>", WIRESHARK_STOCK_COLOR8,},
989     {"/Colorize with Filter/Color 9", NULL, GTK_MENU_FUNC(colorize_selected_ptree_cb), 9, "<StockItem>", WIRESHARK_STOCK_COLOR9,},
990     {"/Colorize with Filter/Color 10", NULL, GTK_MENU_FUNC(colorize_selected_ptree_cb), 10, "<StockItem>", WIRESHARK_STOCK_COLOR0,},
991     {"/Colorize with Filter/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
992     {"/Colorize with Filter/New Coloring Rule...", NULL, GTK_MENU_FUNC(colorize_selected_ptree_cb), 0, "<StockItem>", GTK_STOCK_SELECT_COLOR,},
993
994     {"/Follow TCP Stream", NULL, GTK_MENU_FUNC(follow_tcp_stream_cb),
995                        0, NULL, NULL,},
996     {"/Follow UDP Stream", NULL, GTK_MENU_FUNC(follow_udp_stream_cb),
997                        0, NULL, NULL,},
998     {"/Follow SSL Stream", NULL, GTK_MENU_FUNC(follow_ssl_stream_cb),
999                        0, NULL, NULL,},
1000
1001     {"/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
1002
1003     {"/Copy", NULL, NULL, 0, "<Branch>", NULL,},
1004     {"/Copy/Description", NULL, GTK_MENU_FUNC(copy_selected_plist_cb), 0, NULL, NULL,},
1005     {"/Copy/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
1006     {"/Copy/As Filter", NULL, GTK_MENU_FUNC(match_selected_ptree_cb), MATCH_SELECTED_REPLACE|MATCH_SELECTED_COPY_ONLY, NULL, NULL,},
1007     {"/Copy/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
1008     {"/Copy/Bytes (Offset Hex Text)", NULL, GTK_MENU_FUNC(copy_hex_cb), CD_ALLINFO | CD_FLAGS_SELECTEDONLY, NULL, NULL,},
1009     {"/Copy/Bytes (Offset Hex)", NULL, GTK_MENU_FUNC(copy_hex_cb), CD_HEXCOLUMNS | CD_FLAGS_SELECTEDONLY, NULL, NULL,},
1010     {"/Copy/Bytes (Printable Text Only)", NULL, GTK_MENU_FUNC(copy_hex_cb), CD_TEXTONLY | CD_FLAGS_SELECTEDONLY, NULL, NULL,},
1011     {"/Copy/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
1012     {"/Copy/Bytes (Hex Stream)", NULL, GTK_MENU_FUNC(copy_hex_cb), CD_HEX | CD_FLAGS_SELECTEDONLY, NULL, NULL,},
1013     {"/Copy/Bytes (Binary Stream)", NULL, GTK_MENU_FUNC(copy_hex_cb), CD_BINARY | CD_FLAGS_SELECTEDONLY, NULL, NULL,},
1014
1015     {"/Export Selected Packet Bytes...", NULL, GTK_MENU_FUNC(savehex_cb),
1016                        0, NULL, NULL,},
1017
1018     {"/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
1019
1020     {"/Wiki Protocol Page", NULL, GTK_MENU_FUNC(selected_ptree_info_cb),
1021                        0, "<StockItem>", WIRESHARK_STOCK_WIKI,},
1022     {"/Filter Field Reference", NULL, GTK_MENU_FUNC(selected_ptree_ref_cb),
1023                        0, "<StockItem>", WIRESHARK_STOCK_INTERNET,},
1024     {"/Protocol Preferences...", NULL, GTK_MENU_FUNC(properties_cb),
1025                        0, NULL, NULL,},
1026     {"/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
1027     {"/Decode As...", NULL, GTK_MENU_FUNC(decode_as_cb), 0, "<StockItem>", WIRESHARK_STOCK_DECODE_AS,},
1028     {"/Disable Protocol...", NULL, GTK_MENU_FUNC(proto_disable_cb), 0, "<StockItem>", WIRESHARK_STOCK_CHECKBOX,},
1029     {"/_Resolve Name", NULL, GTK_MENU_FUNC(resolve_name_cb), 0, NULL, NULL,},
1030     {"/_Go to Corresponding Packet", NULL, GTK_MENU_FUNC(goto_framenum_cb), 0, NULL, NULL,}
1031 };
1032
1033
1034 static int initialize = TRUE;
1035 static GtkItemFactory *main_menu_factory = NULL;
1036 static GtkItemFactory *packet_list_menu_factory = NULL;
1037 static GtkItemFactory *tree_view_menu_factory = NULL;
1038 static GtkItemFactory *hexdump_menu_factory = NULL;
1039
1040 static GSList *popup_menu_list = NULL;
1041
1042 static GtkAccelGroup *grp;
1043
1044 GtkWidget *
1045 main_menu_new(GtkAccelGroup ** table) {
1046     GtkWidget *menubar;
1047
1048     grp = gtk_accel_group_new();
1049
1050     if (initialize)
1051         menus_init();
1052
1053     menubar = main_menu_factory->widget;
1054
1055     if (table)
1056         *table = grp;
1057
1058     return menubar;
1059 }
1060
1061
1062 void menu_dissector_filter_cb(  GtkWidget *widget _U_,
1063                                 gpointer callback_data,
1064                                 guint callback_action _U_)
1065 {
1066     dissector_filter_t      *filter_entry = callback_data;
1067     GtkWidget                   *filter_te;
1068     const char              *buf;    
1069
1070
1071     filter_te = g_object_get_data(G_OBJECT(popup_menu_object), E_DFILTER_TE_KEY);
1072
1073     /* XXX - this gets the packet_info of the last dissected packet, */
1074     /* which is not necessarily the last selected packet */
1075     /* e.g. "Update list of packets in real time" won't work correct */
1076     buf = filter_entry->build_filter_string(&cfile.edt->pi);
1077
1078         gtk_entry_set_text(GTK_ENTRY(filter_te), buf);
1079
1080         /* Run the display filter so it goes in effect - even if it's the
1081            same as the previous display filter. */
1082         main_filter_packets(&cfile, buf, TRUE);
1083
1084     g_free( (void *) buf);
1085 }
1086
1087 gboolean menu_dissector_filter_spe_cb(frame_data *fd _U_, epan_dissect_t *edt, gpointer callback_data) {
1088     dissector_filter_t *filter_entry = callback_data;
1089
1090     /* XXX - this gets the packet_info of the last dissected packet, */
1091     /* which is not necessarily the last selected packet */
1092     /* e.g. "Update list of packets in real time" won't work correct */
1093     return (edt != NULL) ? filter_entry->is_filter_valid(&edt->pi) : FALSE;
1094 }
1095
1096 void menu_dissector_filter(void) {
1097     GList *list_entry = dissector_filter_list;
1098     dissector_filter_t *filter_entry;
1099
1100     while(list_entry != NULL) {
1101         filter_entry = list_entry->data;
1102
1103         register_stat_menu_item(filter_entry->name, REGISTER_ANALYZE_GROUP_CONVERSATION_FILTER,
1104             menu_dissector_filter_cb,
1105             menu_dissector_filter_spe_cb,
1106             NULL /* selected_tree_row_enabled */,
1107             filter_entry);
1108
1109         list_entry = g_list_next(list_entry);
1110     }
1111 }
1112
1113
1114 static void
1115 menus_init(void) {
1116   if (initialize) {
1117     initialize = FALSE;
1118
1119     /* popup */
1120     packet_list_menu_factory = gtk_item_factory_new(GTK_TYPE_MENU, "<main>", NULL);
1121     popup_menu_object = gtk_menu_new();
1122     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);
1123     g_object_set_data(G_OBJECT(popup_menu_object), PM_PACKET_LIST_KEY,
1124                     packet_list_menu_factory->widget);
1125     popup_menu_list = g_slist_append((GSList *)popup_menu_list, packet_list_menu_factory);
1126
1127     tree_view_menu_factory = gtk_item_factory_new(GTK_TYPE_MENU, "<main>", NULL);
1128     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);
1129     g_object_set_data(G_OBJECT(popup_menu_object), PM_TREE_VIEW_KEY,
1130                     tree_view_menu_factory->widget);
1131     popup_menu_list = g_slist_append((GSList *)popup_menu_list, tree_view_menu_factory);
1132
1133     hexdump_menu_factory = gtk_item_factory_new(GTK_TYPE_MENU, "<main>", NULL);
1134     g_object_set_data(G_OBJECT(popup_menu_object), PM_HEXDUMP_KEY,
1135                     hexdump_menu_factory->widget);
1136     popup_menu_list = g_slist_append((GSList *)popup_menu_list, hexdump_menu_factory);
1137     /* main */
1138     main_menu_factory = gtk_item_factory_new(GTK_TYPE_MENU_BAR, "<main>", grp);
1139     gtk_item_factory_create_items_ac(main_menu_factory, nmenu_items, menu_items, NULL, 2);
1140
1141     menu_dissector_filter();
1142     merge_all_tap_menus(tap_menu_tree_root);
1143
1144     /* Initialize enabled/disabled state of menu items */
1145     set_menus_for_capture_file(NULL);
1146 #if 0
1147     /* Un-#if this when we actually implement Cut/Copy/Paste.
1148        Then make sure you enable them when they can be done. */
1149     set_menu_sensitivity(main_menu_factory, "/Edit/Cut", FALSE);
1150     set_menu_sensitivity(main_menu_factory, "/Edit/Copy", FALSE);
1151     set_menu_sensitivity(main_menu_factory, "/Edit/Paste", FALSE);
1152 #endif
1153
1154     set_menus_for_captured_packets(FALSE);
1155     set_menus_for_selected_packet(&cfile);
1156     set_menus_for_selected_tree_row(&cfile);
1157     set_menus_for_capture_in_progress(FALSE);
1158     set_menus_for_file_set(/* dialog */TRUE, /* previous file */ FALSE, /* next_file */ FALSE);
1159
1160     /* init with an empty recent files list */
1161     clear_menu_recent_capture_file_cmd_cb(NULL, NULL);
1162
1163   }
1164 }
1165
1166
1167 static gint tap_menu_item_add_compare(gconstpointer a, gconstpointer b)
1168 {
1169     return strcmp(
1170         ((const menu_item_t *) a)->name,
1171         ((const menu_item_t *) b)->name);
1172 }
1173
1174
1175 /* add a menuitem below the current node */
1176 static GList * tap_menu_item_add(
1177     char *name,
1178     gint group,
1179     const char *stock_id,
1180     GtkItemFactoryCallback callback,
1181     gboolean (*selected_packet_enabled)(frame_data *, epan_dissect_t *, gpointer callback_data),
1182     gboolean (*selected_tree_row_enabled)(field_info *, gpointer callback_data),
1183     gpointer callback_data,
1184     GList *curnode)
1185 {
1186     menu_item_t *curr;
1187     menu_item_t *child;
1188
1189
1190     child = g_malloc(sizeof (menu_item_t));
1191     child->name             = name;
1192     child->group            = group;
1193     child->stock_id         = stock_id;
1194     child->callback         = callback;
1195     child->selected_packet_enabled = selected_packet_enabled;
1196     child->selected_tree_row_enabled = selected_tree_row_enabled;
1197     child->callback_data    = callback_data;
1198     child->enabled          = FALSE;
1199     child->children         = NULL;
1200
1201     /* insert the new child node into the parent */
1202     curr = curnode->data;
1203     curr->children = g_list_insert_sorted(curr->children, child, tap_menu_item_add_compare);
1204
1205     /* return the new node */
1206     /* XXX: improve this */
1207     return g_list_find(curr->children, child);
1208 }
1209
1210 /*
1211  * Add a new menu item for a tap.
1212  * This must be called after we've created the main menu, so it can't
1213  * be called from the routine that registers taps - we have to introduce
1214  * another per-tap registration routine.
1215  *
1216  * "callback" gets called when the menu item is selected; it should do
1217  * the work of creating the tap window.
1218  *
1219  * "selected_packet_enabled" gets called by "set_menus_for_selected_packet()";
1220  * it's passed a Boolean that's TRUE if a packet is selected and FALSE
1221  * otherwise, and should return TRUE if the tap will work now (which
1222  * might depend on whether a packet is selected and, if one is, on the
1223  * packet) and FALSE if not.
1224  *
1225  * "selected_tree_row_enabled" gets called by
1226  * "set_menus_for_selected_tree_row()"; it's passed a Boolean that's TRUE if
1227  * a protocol tree row is selected and FALSE otherwise, and should return
1228  * TRUE if the tap will work now (which might depend on whether a tree row
1229  * is selected and, if one is, on the tree row) and FALSE if not.
1230  */
1231 void
1232 register_stat_menu_item_stock(
1233     const char *name,
1234     register_stat_group_t group,
1235     const char *stock_id,
1236     GtkItemFactoryCallback callback,
1237     gboolean (*selected_packet_enabled)(frame_data *, epan_dissect_t *, gpointer callback_data),
1238     gboolean (*selected_tree_row_enabled)(field_info *, gpointer callback_data),
1239     gpointer callback_data)
1240 {
1241     /*static const char toolspath[] = "/Statistics/";*/
1242     const char *toolspath;
1243     const char *p;
1244     char *menupath;
1245     size_t menupathlen;
1246     menu_item_t *child;
1247     GList *curnode;
1248     GList *childnode;
1249
1250     /*
1251      * The menu path must be relative.
1252      */
1253     g_assert(*name != '/');
1254
1255     switch(group) {
1256     case(REGISTER_STAT_GROUP_GENERIC): toolspath = "/Statistics/"; break;
1257     case(REGISTER_STAT_GROUP_CONVERSATION_LIST): toolspath = "/Statistics/_Conversation List/"; break;
1258     case(REGISTER_STAT_GROUP_ENDPOINT_LIST): toolspath = "/Statistics/_Endpoint List/"; break;
1259     case(REGISTER_STAT_GROUP_RESPONSE_TIME): toolspath = "/Statistics/Service _Response Time/"; break;
1260     case(REGISTER_STAT_GROUP_TELEPHONY): toolspath = "/Statistics/"; break;
1261     case(REGISTER_STAT_GROUP_NONE): toolspath = "/Statistics/"; break;
1262     case(REGISTER_ANALYZE_GROUP_NONE): toolspath = "/Analyze/"; break;
1263     case(REGISTER_ANALYZE_GROUP_CONVERSATION_FILTER): toolspath = "/Analyze/Conversation Filter/"; break;
1264     case(REGISTER_TOOLS_GROUP_NONE): toolspath = "/Tools/"; break;
1265     default:
1266         g_assert(!"no such menu group");
1267         toolspath = NULL;
1268     }
1269
1270     /* add the (empty) root node, if not already done */
1271     if(tap_menu_tree_root == NULL) {
1272         child = g_malloc0(sizeof (menu_item_t));
1273         tap_menu_tree_root = g_list_append(NULL, child);
1274     }
1275
1276     /*
1277      * Create any submenus required.
1278      */
1279     curnode = tap_menu_tree_root;
1280     p = name;
1281     while ((p = strchr(p, '/')) != NULL) {
1282         /*
1283          * OK, everything between "name" and "p" is
1284          * a menu relative subtree into which the menu item
1285          * will be placed.
1286          *
1287          * Construct the absolute path name of that subtree.
1288          */
1289         menupathlen = strlen(toolspath) + 1 + (p - name);
1290         menupath = g_malloc(menupathlen);
1291         g_strlcpy(menupath, toolspath, menupathlen);
1292         g_strlcat(menupath, name, menupathlen);
1293
1294         /*
1295          * Does there exist an entry with that path at this
1296          * level of the Analyze menu tree?
1297          */
1298         child = curnode->data;
1299         for (childnode = child->children; childnode != NULL; childnode = childnode->next) {
1300             child = childnode->data;
1301             if (strcmp(child->name, menupath) == 0)
1302                 break;
1303         }
1304         if (childnode == NULL) {
1305             /*
1306              * No.  Create such an item as a subtree, and
1307              * add it to the Tools menu tree.
1308              */
1309             childnode = tap_menu_item_add(
1310                 menupath, group, "", NULL, NULL ,NULL, NULL, curnode);
1311         } else {
1312             /*
1313              * Yes.  We don't need this "menupath" any longer.
1314              */
1315             g_free(menupath);
1316         }
1317         curnode = childnode;
1318
1319         /*
1320          * Skip over the '/' we found.
1321          */
1322         p++;
1323     }
1324
1325     /*
1326      * Construct the main menu path for the menu item.
1327      */
1328     menupathlen = strlen(toolspath) + 1 + strlen(name);
1329     menupath = g_malloc(menupathlen);
1330     g_strlcpy(menupath, toolspath, menupathlen);
1331     g_strlcat(menupath, name, menupathlen);
1332
1333     /*
1334      * Construct an item factory entry for the item, and add it to
1335      * the main menu.
1336      */
1337     tap_menu_item_add(
1338         menupath, group, stock_id, callback,
1339         selected_packet_enabled, selected_tree_row_enabled,
1340         callback_data, curnode);
1341 }
1342
1343
1344 void
1345 register_stat_menu_item(
1346     const char *name,
1347     register_stat_group_t group,
1348     GtkItemFactoryCallback callback,
1349     gboolean (*selected_packet_enabled)(frame_data *, epan_dissect_t *, gpointer callback_data),
1350     gboolean (*selected_tree_row_enabled)(field_info *, gpointer callback_data),
1351     gpointer callback_data)
1352 {
1353     register_stat_menu_item_stock(
1354         name,
1355         group,
1356         NULL,
1357         callback,
1358         selected_packet_enabled,
1359         selected_tree_row_enabled,
1360         callback_data);
1361 }
1362
1363 static guint merge_tap_menus_layered(GList *node, gint group) {
1364     GtkItemFactoryEntry *entry;
1365     GList       *child;
1366     guint       added = 0;
1367     menu_item_t *node_data = node->data;
1368
1369     /*
1370      * Is this a leaf node or an interior node?
1371      */
1372     if (node_data->children == NULL) {
1373         /*
1374          * It's a leaf node.
1375          */
1376
1377         /*
1378          * The root node doesn't correspond to a menu tree item; it
1379          * has a null name pointer.
1380          */
1381         if (node_data->name != NULL && group == node_data->group) {
1382             entry = g_malloc0(sizeof (GtkItemFactoryEntry));
1383             entry->path = node_data->name;
1384             entry->callback = node_data->callback;
1385             switch(group) {
1386             case(REGISTER_STAT_GROUP_NONE):
1387                 break;
1388             case(REGISTER_STAT_GROUP_GENERIC):
1389                 break;
1390             case(REGISTER_STAT_GROUP_CONVERSATION_LIST):
1391                 entry->item_type = "<StockItem>";
1392                 entry->extra_data = WIRESHARK_STOCK_CONVERSATIONS;
1393                 break;
1394             case(REGISTER_STAT_GROUP_ENDPOINT_LIST):
1395                 entry->item_type = "<StockItem>";
1396                 entry->extra_data = WIRESHARK_STOCK_ENDPOINTS;
1397                 break;
1398             case(REGISTER_STAT_GROUP_RESPONSE_TIME):
1399                 entry->item_type = "<StockItem>";
1400                 entry->extra_data = WIRESHARK_STOCK_TIME;
1401                 break;
1402             case(REGISTER_STAT_GROUP_TELEPHONY):
1403                 entry->item_type = "<StockItem>";
1404                 entry->extra_data = WIRESHARK_STOCK_TELEPHONY;
1405                 break;
1406             case(REGISTER_ANALYZE_GROUP_NONE):
1407                 break;
1408             case(REGISTER_ANALYZE_GROUP_CONVERSATION_FILTER):
1409                 break;
1410             case(REGISTER_TOOLS_GROUP_NONE):
1411                 break;
1412             default:
1413                 g_assert_not_reached();
1414             }
1415             if(node_data->stock_id!= NULL) {
1416                 entry->item_type = "<StockItem>";
1417                 entry->extra_data = node_data->stock_id;
1418             }
1419             gtk_item_factory_create_item(main_menu_factory, entry, node_data->callback_data, /* callback_type */ 2);
1420             set_menu_sensitivity(main_menu_factory, node_data->name, FALSE); /* no capture file yet */
1421             added++;
1422             g_free(entry);
1423         }
1424     } else {
1425         /*
1426          * It's an interior node; call
1427          * "merge_tap_menus_layered()" on all its children
1428          */
1429
1430         /*
1431          * The root node doesn't correspond to a menu tree item; it
1432          * has a null name pointer.
1433          */
1434         if (node_data->name != NULL && group == node_data->group) {
1435             entry = g_malloc0(sizeof (GtkItemFactoryEntry));
1436             entry->path = node_data->name;
1437             entry->item_type = "<Branch>";
1438             gtk_item_factory_create_item(main_menu_factory, entry,
1439                 NULL, 2);
1440             set_menu_sensitivity(main_menu_factory, node_data->name,
1441                 FALSE);    /* no children yet */
1442             added++;
1443             g_free(entry);
1444         }
1445
1446         for (child = node_data->children; child != NULL; child =
1447             child->next) {
1448             added += merge_tap_menus_layered(child, group);
1449         }
1450     }
1451
1452     return added;
1453 }
1454
1455
1456 void merge_all_tap_menus(GList *node) {
1457     GtkItemFactoryEntry *sep_entry;
1458
1459     sep_entry = g_malloc0(sizeof (GtkItemFactoryEntry));
1460     sep_entry->item_type = "<Separator>";
1461     sep_entry->path = "/Statistics/";
1462
1463     /*
1464      * merge only the menu items of the specific group,
1465      * and then append a seperator
1466      */
1467     if (merge_tap_menus_layered(node, REGISTER_STAT_GROUP_GENERIC)) {
1468         gtk_item_factory_create_item(main_menu_factory, sep_entry, NULL, 2);
1469     }
1470     if (merge_tap_menus_layered(node, REGISTER_STAT_GROUP_CONVERSATION_LIST)) {
1471         /*gtk_item_factory_create_item(main_menu_factory, sep_entry, NULL, 2);*/
1472     }
1473     if (merge_tap_menus_layered(node, REGISTER_STAT_GROUP_ENDPOINT_LIST)) {
1474         /*gtk_item_factory_create_item(main_menu_factory, sep_entry, NULL, 2);*/
1475     }
1476     if (merge_tap_menus_layered(node, REGISTER_STAT_GROUP_RESPONSE_TIME)) {
1477         gtk_item_factory_create_item(main_menu_factory, sep_entry, NULL, 2);
1478     }
1479     if (merge_tap_menus_layered(node, REGISTER_STAT_GROUP_TELEPHONY)) {
1480         gtk_item_factory_create_item(main_menu_factory, sep_entry, NULL, 2);
1481     }
1482     if (merge_tap_menus_layered(node, REGISTER_STAT_GROUP_NONE)) {
1483         /*gtk_item_factory_create_item(main_menu_factory, sep_entry, NULL, 2);*/
1484     }
1485     if (merge_tap_menus_layered(node, REGISTER_ANALYZE_GROUP_NONE)) {
1486         sep_entry->path = "/Analyze/";
1487         /*gtk_item_factory_create_item(main_menu_factory, sep_entry, NULL, 2);*/
1488     }
1489     if (merge_tap_menus_layered(node, REGISTER_ANALYZE_GROUP_CONVERSATION_FILTER)) {
1490         sep_entry->path = "/Analyze/Conversation Filter/";
1491         /*gtk_item_factory_create_item(main_menu_factory, sep_entry, NULL, 2);*/
1492     }
1493     if (merge_tap_menus_layered(node, REGISTER_TOOLS_GROUP_NONE)) {
1494         /*gtk_item_factory_create_item(main_menu_factory, sep_entry, NULL, 2);*/
1495     }
1496 }
1497
1498
1499
1500 /*
1501  * Enable/disable menu sensitivity.
1502  */
1503 static void
1504 set_menu_sensitivity(GtkItemFactory *ifactory, const gchar *path, gint val)
1505 {
1506   GSList *menu_list;
1507   GtkWidget *menu_item;
1508   gchar *dup;
1509   gchar *dest;
1510
1511
1512   /* the underscore character regularly confuses things, as it will prevent finding
1513    * the menu_item, so it has to be removed first */
1514   dup = g_strdup(path);
1515   dest = dup;
1516   while(*path) {
1517       if (*path != '_') {
1518         *dest = *path;
1519         dest++;
1520       }
1521       path++;
1522   }
1523   *dest = '\0';
1524
1525   if (ifactory == NULL) {
1526     /*
1527      * Do it for all pop-up menus.
1528      */
1529     for (menu_list = popup_menu_list; menu_list != NULL;
1530          menu_list = g_slist_next(menu_list))
1531       set_menu_sensitivity(menu_list->data, dup, val);
1532   } else {
1533     /*
1534      * Do it for that particular menu.
1535      */
1536     if ((menu_item = gtk_item_factory_get_widget(ifactory, dup)) != NULL) {
1537       if (GTK_IS_MENU(menu_item)) {
1538         /*
1539          * "dup" refers to a submenu; "gtk_item_factory_get_widget()"
1540          * gets the menu, not the item that, when selected, pops up
1541          * the submenu.
1542          *
1543          * We have to change the latter item's sensitivity, so that
1544          * it shows up normally if sensitive and grayed-out if
1545          * insensitive.
1546          */
1547         menu_item = gtk_menu_get_attach_widget(GTK_MENU(menu_item));
1548       }
1549       gtk_widget_set_sensitive(menu_item, val);
1550     } else{
1551       /* be sure this menu item *is* existing */
1552       g_assert_not_reached();
1553     }
1554   }
1555
1556   g_free(dup);
1557 }
1558
1559 static void
1560 set_menu_object_data_meat(GtkItemFactory *ifactory, const gchar *path, const gchar *key, gpointer data)
1561 {
1562         GtkWidget *menu = NULL;
1563
1564         if ((menu = gtk_item_factory_get_widget(ifactory, path)) != NULL)
1565                 g_object_set_data(G_OBJECT(menu), key, data);
1566 }
1567
1568 void
1569 set_menu_object_data (const gchar *path, const gchar *key, gpointer data) {
1570   GSList *menu_list = popup_menu_list;
1571   gchar *shortpath = strrchr(path, '/');
1572
1573   set_menu_object_data_meat(main_menu_factory, path, key, data);
1574   while (menu_list != NULL) {
1575     set_menu_object_data_meat(menu_list->data, shortpath, key, data);
1576     set_menu_object_data_meat(menu_list->data, path, key, data);
1577     menu_list = g_slist_next(menu_list);
1578   }
1579 }
1580
1581
1582 /* Recently used capture files submenu:
1583  * Submenu containing the recently used capture files.
1584  * The capture filenames are always kept with the absolute path, to be independant
1585  * of the current path.
1586  * They are only stored inside the labels of the submenu (no separate list). */
1587
1588 #define MENU_RECENT_FILES_PATH "/File/Open Recent"
1589 #define MENU_RECENT_FILES_KEY "Recent File Name"
1590
1591 static void
1592 update_menu_recent_capture_file1(GtkWidget *widget, gpointer cnt) {
1593     gchar *widget_cf_name;
1594
1595     widget_cf_name = g_object_get_data(G_OBJECT(widget), MENU_RECENT_FILES_KEY);
1596
1597     /* if this menu item is a file, count it */
1598     if (widget_cf_name) {
1599         (*(guint *)cnt)++;
1600     }
1601 }
1602
1603
1604 /* update the menu */
1605 static void
1606 update_menu_recent_capture_file(GtkWidget *submenu_recent_files) {
1607     guint cnt = 0;
1608
1609     gtk_container_foreach(GTK_CONTAINER(submenu_recent_files),
1610                 update_menu_recent_capture_file1, &cnt);
1611
1612     /* make parent menu item sensitive only, if we have any valid files in the list */
1613     set_menu_sensitivity(main_menu_factory, MENU_RECENT_FILES_PATH, cnt);
1614 }
1615
1616
1617 /* remove the capture filename from the "Recent Files" menu */
1618 static void
1619 remove_menu_recent_capture_file(GtkWidget *widget, gpointer unused _U_) {
1620     GtkWidget *submenu_recent_files;
1621     gchar *widget_cf_name;
1622
1623
1624     widget_cf_name = g_object_get_data(G_OBJECT(widget), MENU_RECENT_FILES_KEY);
1625     g_free(widget_cf_name);
1626
1627     /* get the submenu container item */
1628     submenu_recent_files = gtk_item_factory_get_widget(main_menu_factory, MENU_RECENT_FILES_PATH);
1629
1630     /* XXX: is this all we need to do, to free the menu item and its label?
1631        The reference count of widget will go to 0, so it'll be freed;
1632        will that free the label? */
1633     gtk_container_remove(GTK_CONTAINER(submenu_recent_files), widget);
1634 }
1635
1636
1637 /* callback, if the user pushed the <Clear File List> item */
1638 static void
1639 clear_menu_recent_capture_file_cmd_cb(GtkWidget *w _U_, gpointer unused _U_) {
1640     GtkWidget *submenu_recent_files;
1641
1642
1643     submenu_recent_files = gtk_item_factory_get_widget(main_menu_factory, MENU_RECENT_FILES_PATH);
1644
1645     gtk_container_foreach(GTK_CONTAINER(submenu_recent_files),
1646                 remove_menu_recent_capture_file, NULL);
1647
1648     update_menu_recent_capture_file(submenu_recent_files);
1649 }
1650
1651
1652 /* callback, if the user pushed a recent file submenu item */
1653 void
1654 menu_open_recent_file_cmd(GtkWidget *w)
1655 {
1656         GtkWidget *submenu_recent_files;
1657         GtkWidget *menu_item_child;
1658         gchar     *cf_name;
1659         int       err;
1660
1661         submenu_recent_files = gtk_item_factory_get_widget(main_menu_factory, MENU_RECENT_FILES_PATH);
1662
1663         /* get capture filename from the menu item label */
1664         menu_item_child = (GTK_BIN(w))->child;
1665         gtk_label_get(GTK_LABEL(menu_item_child), &cf_name);
1666
1667         /* open and read the capture file (this will close an existing file) */
1668         if (cf_open(&cfile, cf_name, FALSE, &err) == CF_OK) {
1669                 cf_read(&cfile);
1670         } else {
1671                 /* the capture file isn't existing any longer, remove menu item */
1672                 /* XXX: ask user to remove item, it's maybe only a temporary problem */
1673                 remove_menu_recent_capture_file(w, NULL);
1674         }
1675
1676         update_menu_recent_capture_file(submenu_recent_files);
1677 }
1678
1679 static void menu_open_recent_file_answered_cb(gpointer dialog _U_, gint btn, gpointer data _U_)
1680 {
1681     switch(btn) {
1682     case(ESD_BTN_YES):
1683         /* save file first */
1684         file_save_as_cmd(after_save_open_recent_file, data);
1685         break;
1686     case(ESD_BTN_NO):
1687         cf_close(&cfile);
1688         menu_open_recent_file_cmd(data);
1689         break;
1690     case(ESD_BTN_CANCEL):
1691         break;
1692     default:
1693         g_assert_not_reached();
1694     }
1695 }
1696
1697 static void
1698 menu_open_recent_file_cmd_cb(GtkWidget *widget, gpointer data _U_) {
1699   gpointer  dialog;
1700
1701
1702   if((cfile.state != FILE_CLOSED) && !cfile.user_saved && prefs.gui_ask_unsaved) {
1703     /* user didn't saved his current file, ask him */
1704     dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_YES_NO_CANCEL,
1705                 "%sSave capture file before opening a new one?%s\n\n"
1706                 "If you open a new capture file without saving, your current capture data will be discarded.",
1707                 simple_dialog_primary_start(), simple_dialog_primary_end());
1708     simple_dialog_set_cb(dialog, menu_open_recent_file_answered_cb, widget);
1709   } else {
1710     /* unchanged file */
1711     menu_open_recent_file_cmd(widget);
1712   }
1713 }
1714
1715 /* add the capture filename (with an absolute path) to the "Recent Files" menu */
1716 static void
1717 add_menu_recent_capture_file_absolute(gchar *cf_name) {
1718         GtkWidget *submenu_recent_files;
1719         GList *menu_item_list;
1720         GList *li;
1721         gchar *widget_cf_name;
1722         gchar *normalized_cf_name;
1723         GtkWidget *menu_item;
1724         guint cnt;
1725
1726
1727
1728         normalized_cf_name = g_strdup(cf_name);
1729 #ifdef _WIN32
1730         /* replace all slashes by backslashes */
1731         g_strdelimit(normalized_cf_name, "/", '\\');
1732 #endif
1733
1734         /* get the submenu container item */
1735         submenu_recent_files = gtk_item_factory_get_widget(main_menu_factory, MENU_RECENT_FILES_PATH);
1736
1737         /* convert container to a GList */
1738         menu_item_list = gtk_container_children(GTK_CONTAINER(submenu_recent_files));
1739
1740         /* iterate through list items of menu_item_list,
1741          * removing special items, a maybe duplicate entry and every item above count_max */
1742         cnt = 1;
1743         for (li = g_list_first(menu_item_list); li; li = li->next, cnt++) {
1744                 /* get capture filename */
1745                 menu_item = GTK_WIDGET(li->data);
1746                 widget_cf_name = g_object_get_data(G_OBJECT(menu_item), MENU_RECENT_FILES_KEY);
1747
1748                 /* if this element string is one of our special items (seperator, ...) or
1749                  * already in the list or
1750                  * this element is above maximum count (too old), remove it */
1751                 if (!widget_cf_name ||
1752 #ifdef _WIN32
1753                     /* do a case insensitive compare on win32 */
1754                     g_ascii_strncasecmp(widget_cf_name, normalized_cf_name, 1000) == 0 ||
1755 #else   /* _WIN32 */
1756                     /* do a case sensitive compare on unix */
1757                     strncmp(widget_cf_name, normalized_cf_name, 1000) == 0 ||
1758 #endif
1759                     cnt >= prefs.gui_recent_files_count_max) {
1760                         remove_menu_recent_capture_file(li->data, NULL);
1761                         cnt--;
1762                 }
1763         }
1764
1765         g_list_free(menu_item_list);
1766
1767         /* add new item at latest position */
1768         menu_item = gtk_menu_item_new_with_label(normalized_cf_name);
1769         g_object_set_data(G_OBJECT(menu_item), MENU_RECENT_FILES_KEY, normalized_cf_name);
1770         gtk_menu_prepend (GTK_MENU(submenu_recent_files), menu_item);
1771         g_signal_connect_swapped(GTK_OBJECT(menu_item), "activate",
1772                 G_CALLBACK(menu_open_recent_file_cmd_cb), (GtkObject *) menu_item);
1773         gtk_widget_show (menu_item);
1774
1775         /* add seperator at last position */
1776         menu_item = gtk_menu_item_new();
1777         gtk_menu_append (GTK_MENU(submenu_recent_files), menu_item);
1778         gtk_widget_show (menu_item);
1779
1780         /* add new "clear list" item at last position */
1781         menu_item = gtk_image_menu_item_new_from_stock(GTK_STOCK_CLEAR, NULL);
1782         gtk_menu_append (GTK_MENU(submenu_recent_files), menu_item);
1783         g_signal_connect_swapped(GTK_OBJECT(menu_item), "activate",
1784                 G_CALLBACK(clear_menu_recent_capture_file_cmd_cb), (GtkObject *) menu_item);
1785         gtk_widget_show (menu_item);
1786
1787         update_menu_recent_capture_file(submenu_recent_files);
1788 }
1789
1790
1791 /* add the capture filename to the "Recent Files" menu */
1792 /* (will change nothing, if this filename is already in the menu) */
1793 void
1794 add_menu_recent_capture_file(gchar *cf_name) {
1795         gchar *curr;
1796         gchar *absolute;
1797
1798
1799         /* if this filename is an absolute path, we can use it directly */
1800         if (g_path_is_absolute(cf_name)) {
1801                 add_menu_recent_capture_file_absolute(cf_name);
1802                 return;
1803         }
1804
1805         /* this filename is not an absolute path, prepend the current dir */
1806         curr = g_get_current_dir();
1807         absolute = g_strdup_printf("%s%s%s", curr, G_DIR_SEPARATOR_S, cf_name);
1808         add_menu_recent_capture_file_absolute(absolute);
1809         g_free(curr);
1810         g_free(absolute);
1811 }
1812
1813
1814 /* write all capture filenames of the menu to the user's recent file */
1815 void
1816 menu_recent_file_write_all(FILE *rf) {
1817     GtkWidget   *submenu_recent_files;
1818     GList       *children;
1819     GList       *child;
1820     gchar       *cf_name;
1821
1822
1823     submenu_recent_files = gtk_item_factory_get_widget(main_menu_factory, MENU_RECENT_FILES_PATH);
1824
1825     /* we have to iterate backwards through the children's list,
1826      * so we get the latest item last in the file.
1827      * (don't use gtk_container_foreach() here, it will return the wrong iteration order) */
1828     children = gtk_container_children(GTK_CONTAINER(submenu_recent_files));
1829     child = g_list_last(children);
1830     while(child != NULL) {
1831         /* get capture filename from the menu item label */
1832         cf_name = g_object_get_data(G_OBJECT(child->data), MENU_RECENT_FILES_KEY);
1833         if (cf_name) {
1834             if(u3_active())
1835                 fprintf (rf, RECENT_KEY_CAPTURE_FILE ": %s\n", u3_contract_device_path(cf_name));
1836             else
1837                 fprintf (rf, RECENT_KEY_CAPTURE_FILE ": %s\n", cf_name);
1838         }
1839
1840         child = g_list_previous(child);
1841     }
1842
1843     g_list_free(children);
1844 }
1845
1846
1847 static void
1848 show_hide_cb(GtkWidget *w, gpointer data _U_, gint action)
1849 {
1850
1851     /* save current setting in recent */
1852     switch(action) {
1853         case(SHOW_HIDE_MAIN_TOOLBAR):
1854         recent.main_toolbar_show = GTK_CHECK_MENU_ITEM(w)->active;
1855         break;
1856         case(SHOW_HIDE_FILTER_TOOLBAR):
1857         recent.filter_toolbar_show = GTK_CHECK_MENU_ITEM(w)->active;
1858         break;
1859 #ifdef HAVE_AIRPCAP
1860         case(SHOW_HIDE_AIRPCAP_TOOLBAR):
1861         recent.airpcap_toolbar_show = GTK_CHECK_MENU_ITEM(w)->active;
1862         break;
1863 #endif
1864         case(SHOW_HIDE_STATUSBAR):
1865         recent.statusbar_show = GTK_CHECK_MENU_ITEM(w)->active;
1866         break;
1867         case(SHOW_HIDE_PACKET_LIST):
1868         recent.packet_list_show = GTK_CHECK_MENU_ITEM(w)->active;
1869         break;
1870         case(SHOW_HIDE_TREE_VIEW):
1871         recent.tree_view_show = GTK_CHECK_MENU_ITEM(w)->active;
1872         break;
1873         case(SHOW_HIDE_BYTE_VIEW):
1874         recent.byte_view_show = GTK_CHECK_MENU_ITEM(w)->active;
1875         break;
1876         default:
1877             g_assert_not_reached();
1878     }
1879
1880     main_widgets_show_or_hide();
1881 }
1882
1883
1884 static void
1885 timestamp_format_cb(GtkWidget *w _U_, gpointer d _U_, gint action)
1886 {
1887     if (recent.gui_time_format != action) {
1888         timestamp_set_type(action);
1889         recent.gui_time_format = action;
1890         cf_change_time_formats(&cfile);
1891     }
1892 }
1893
1894
1895 static void
1896 timestamp_precision_cb(GtkWidget *w _U_, gpointer d _U_, gint action)
1897 {
1898     if (recent.gui_time_precision != action) {
1899                 /* the actual precision will be set in cf_change_time_formats() below */
1900         if(action == TS_PREC_AUTO) {
1901             timestamp_set_precision(TS_PREC_AUTO_SEC);
1902         } else {
1903             timestamp_set_precision(action);
1904         }
1905         recent.gui_time_precision  = action;
1906         cf_change_time_formats(&cfile);
1907     }
1908 }
1909
1910
1911 void
1912 menu_name_resolution_changed(void)
1913 {
1914     GtkWidget *menu = NULL;
1915
1916     menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Name Resolution/Enable for MAC Layer");
1917     gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), g_resolv_flags & RESOLV_MAC);
1918
1919     menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Name Resolution/Enable for Network Layer");
1920     gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), g_resolv_flags & RESOLV_NETWORK);
1921
1922     menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Name Resolution/Enable for Transport Layer");
1923     gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), g_resolv_flags & RESOLV_TRANSPORT);
1924 }
1925
1926 static void
1927 name_resolution_cb(GtkWidget *w, gpointer d _U_, gint action)
1928 {
1929     if (GTK_CHECK_MENU_ITEM(w)->active) {
1930         g_resolv_flags |= action;
1931     } else {
1932         g_resolv_flags &= ~action;
1933     }
1934 }
1935
1936 #ifdef HAVE_LIBPCAP
1937 void
1938 menu_auto_scroll_live_changed(gboolean auto_scroll_live_in) {
1939     GtkWidget *menu;
1940
1941
1942     /* tell menu about it */
1943     menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Auto Scroll in Live Capture");
1944     if( ((gboolean) GTK_CHECK_MENU_ITEM(menu)->active) != auto_scroll_live_in) {
1945         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), auto_scroll_live_in);
1946     }
1947
1948     /* tell toolbar about it */
1949     toolbar_auto_scroll_live_changed(auto_scroll_live_in);
1950
1951     /* change auto scroll */
1952     if(auto_scroll_live_in != auto_scroll_live) {
1953         auto_scroll_live  = auto_scroll_live_in;
1954     }
1955 }
1956
1957 static void
1958 auto_scroll_live_cb(GtkWidget *w _U_, gpointer d _U_)
1959 {
1960     menu_auto_scroll_live_changed(GTK_CHECK_MENU_ITEM(w)->active);
1961 }
1962 #endif
1963
1964
1965 void
1966 menu_colorize_changed(gboolean packet_list_colorize) {
1967     GtkWidget *menu;
1968
1969
1970     /* tell menu about it */
1971     menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Colorize Packet List");
1972     if( ((gboolean) GTK_CHECK_MENU_ITEM(menu)->active) != packet_list_colorize) {
1973         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), packet_list_colorize);
1974     }
1975
1976     /* tell toolbar about it */
1977     toolbar_colorize_changed(packet_list_colorize);
1978
1979     /* change colorization */
1980     if(packet_list_colorize != recent.packet_list_colorize) {
1981         recent.packet_list_colorize = packet_list_colorize;
1982         color_filters_enable(packet_list_colorize);
1983         cf_colorize_packets(&cfile);
1984     }
1985 }
1986
1987 static void
1988 colorize_cb(GtkWidget *w, gpointer d _U_)
1989 {
1990     menu_colorize_changed(GTK_CHECK_MENU_ITEM(w)->active);
1991 }
1992
1993
1994 /* the recent file read has finished, update the menu corresponding */
1995 void
1996 menu_recent_read_finished(void) {
1997     GtkWidget *menu = NULL;
1998
1999     menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Main Toolbar");
2000     gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), recent.main_toolbar_show);
2001
2002     menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Filter Toolbar");
2003     gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), recent.filter_toolbar_show);
2004
2005 #ifdef HAVE_AIRPCAP
2006     menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Wireless Toolbar");
2007     gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), recent.airpcap_toolbar_show);
2008 #endif
2009
2010     menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Statusbar");
2011     gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), recent.statusbar_show);
2012
2013     menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Packet List");
2014     gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), recent.packet_list_show);
2015
2016     menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Packet Details");
2017     gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), recent.tree_view_show);
2018
2019     menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Packet Bytes");
2020     gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), recent.byte_view_show);
2021
2022     menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Colorize Packet List");
2023     gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), recent.packet_list_colorize);
2024
2025     menu_name_resolution_changed();
2026
2027 #ifdef HAVE_LIBPCAP
2028     menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Auto Scroll in Live Capture");
2029     gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), auto_scroll_live);
2030 #endif
2031
2032     main_widgets_rearrange();
2033
2034     /* don't change the time format, if we had a command line value */
2035     if (timestamp_get_type() != TS_NOT_SET) {
2036         recent.gui_time_format = timestamp_get_type();
2037     }
2038
2039     switch(recent.gui_time_format) {
2040     case(TS_ABSOLUTE_WITH_DATE):
2041         menu = gtk_item_factory_get_widget(main_menu_factory,
2042             "/View/Time Display Format/Date and Time of Day:   1970-01-01 01:02:03.123456");
2043         /* set_active will not trigger the callback when activating an active item! */
2044         recent.gui_time_format = -1;
2045         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), FALSE);
2046         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), TRUE);
2047         break;
2048     case(TS_ABSOLUTE):
2049         menu = gtk_item_factory_get_widget(main_menu_factory,
2050             "/View/Time Display Format/Time of Day:   01:02:03.123456");
2051         /* set_active will not trigger the callback when activating an active item! */
2052         recent.gui_time_format = -1;
2053         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), TRUE);
2054         break;
2055     case(TS_RELATIVE):
2056         menu = gtk_item_factory_get_widget(main_menu_factory,
2057             "/View/Time Display Format/Seconds Since Beginning of Capture:   123.123456");
2058         recent.gui_time_format = -1;
2059         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), TRUE);
2060         break;
2061     case(TS_DELTA):
2062         menu = gtk_item_factory_get_widget(main_menu_factory,
2063             "/View/Time Display Format/Seconds Since Previous Captured Packet:   1.123456");
2064         recent.gui_time_format = -1;
2065         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), TRUE);
2066         break;
2067     case(TS_DELTA_DIS):
2068         menu = gtk_item_factory_get_widget(main_menu_factory,
2069             "/View/Time Display Format/Seconds Since Previous Displayed Packet:   1.123456");
2070         recent.gui_time_format = -1;
2071         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), TRUE);
2072         break;
2073     case(TS_EPOCH):
2074         menu = gtk_item_factory_get_widget(main_menu_factory,
2075             "/View/Time Display Format/Seconds Since Epoch (1970-01-01):   1234567890.123456");
2076         recent.gui_time_format = -1;
2077         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), TRUE);
2078         break;
2079     default:
2080         g_assert_not_reached();
2081     }
2082
2083     switch(recent.gui_time_precision) {
2084     case(TS_PREC_AUTO):
2085         menu = gtk_item_factory_get_widget(main_menu_factory,
2086             "/View/Time Display Format/Automatic (File Format Precision)");
2087         /* set_active will not trigger the callback when activating an active item! */
2088         recent.gui_time_precision = -1;
2089         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), FALSE);
2090         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), TRUE);
2091         break;
2092     case(TS_PREC_FIXED_SEC):
2093         menu = gtk_item_factory_get_widget(main_menu_factory,
2094             "/View/Time Display Format/Seconds:   0");
2095         recent.gui_time_precision = -1;
2096         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), TRUE);
2097         break;
2098     case(TS_PREC_FIXED_DSEC):
2099         menu = gtk_item_factory_get_widget(main_menu_factory,
2100             "/View/Time Display Format/Deciseconds:   0.1");
2101         recent.gui_time_precision = -1;
2102         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), TRUE);
2103         break;
2104     case(TS_PREC_FIXED_CSEC):
2105         menu = gtk_item_factory_get_widget(main_menu_factory,
2106             "/View/Time Display Format/Centiseconds:   0.12");
2107         recent.gui_time_precision = -1;
2108         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), TRUE);
2109         break;
2110     case(TS_PREC_FIXED_MSEC):
2111         menu = gtk_item_factory_get_widget(main_menu_factory,
2112             "/View/Time Display Format/Milliseconds:   0.123");
2113         recent.gui_time_precision = -1;
2114         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), TRUE);
2115         break;
2116     case(TS_PREC_FIXED_USEC):
2117         menu = gtk_item_factory_get_widget(main_menu_factory,
2118             "/View/Time Display Format/Microseconds:   0.123456");
2119         recent.gui_time_precision = -1;
2120         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), TRUE);
2121         break;
2122     case(TS_PREC_FIXED_NSEC):
2123         menu = gtk_item_factory_get_widget(main_menu_factory,
2124             "/View/Time Display Format/Nanoseconds:   0.123456789");
2125         recent.gui_time_precision = -1;
2126         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), TRUE);
2127         break;
2128     default:
2129         g_assert_not_reached();
2130     }
2131
2132     menu_colorize_changed(recent.packet_list_colorize);
2133 }
2134
2135
2136 gint
2137 popup_menu_handler(GtkWidget *widget, GdkEvent *event, gpointer data)
2138 {
2139     GtkWidget *menu = (GtkWidget *)data;
2140     GdkEventButton *event_button = NULL;
2141     gint row, column;
2142
2143     if(widget == NULL || event == NULL || data == NULL) {
2144         return FALSE;
2145     }
2146
2147     /*
2148      * If we ever want to make the menu differ based on what row
2149      * and/or column we're above, we'd use "eth_clist_get_selection_info()"
2150      * to find the row and column number for the coordinates; a CTree is,
2151      * I guess, like a CList with one column(?) and the expander widget
2152      * as a pixmap.
2153      */
2154     /* Check if we are on packet_list object */
2155     if (widget == g_object_get_data(G_OBJECT(popup_menu_object), E_MPACKET_LIST_KEY) &&
2156         ((GdkEventButton *)event)->button != 1) {
2157         if (packet_list_get_event_row_column(widget, (GdkEventButton *)event,
2158                                              &row, &column)) {
2159             g_object_set_data(G_OBJECT(popup_menu_object), E_MPACKET_LIST_ROW_KEY,
2160                             GINT_TO_POINTER(row));
2161             g_object_set_data(G_OBJECT(popup_menu_object), E_MPACKET_LIST_COL_KEY,
2162                             GINT_TO_POINTER(column));
2163             packet_list_set_selected_row(row);
2164         }
2165     }
2166
2167     /* Check if we are on tree_view object */
2168     if (widget == tree_view) {
2169         tree_view_select(widget, (GdkEventButton *) event);
2170     }
2171
2172     /* Check if we are on byte_view object */
2173     if(widget == get_notebook_bv_ptr(byte_nb_ptr)) {
2174         byte_view_select(widget, (GdkEventButton *) event);
2175     }
2176
2177     /* context menu handler (but the byte view notebook pages have their own handler) */
2178     if(event->type == GDK_BUTTON_PRESS && widget != byte_nb_ptr) {
2179         event_button = (GdkEventButton *) event;
2180
2181         /* To qoute the "Gdk Event Structures" doc:
2182          * "Normally button 1 is the left mouse button, 2 is the middle button, and 3 is the right button" */
2183         if(event_button->button == 3) {
2184             gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL,
2185                            event_button->button,
2186                            event_button->time);
2187             g_signal_stop_emission_by_name(widget, "button_press_event");
2188             return TRUE;
2189         }
2190     }
2191     /* GDK_2BUTTON_PRESS is a doubleclick -> expand/collapse tree row */
2192     /* GTK version 1 seems to be doing this automatically */
2193     if (widget == tree_view && event->type == GDK_2BUTTON_PRESS) {
2194         GtkTreePath      *path;
2195
2196         if (gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(widget),
2197                                           (gint) (((GdkEventButton *)event)->x),
2198                                           (gint) (((GdkEventButton *)event)->y),
2199                                           &path, NULL, NULL, NULL))
2200         {
2201             if (gtk_tree_view_row_expanded(GTK_TREE_VIEW(widget), path))
2202                 gtk_tree_view_collapse_row(GTK_TREE_VIEW(widget), path);
2203             else
2204                 gtk_tree_view_expand_row(GTK_TREE_VIEW(widget), path,
2205                                          FALSE);
2206             gtk_tree_path_free(path);
2207         }
2208     }
2209     return FALSE;
2210 }
2211
2212 /* Enable or disable menu items based on whether you have a capture file
2213    you've finished reading and, if you have one, whether it's been saved
2214    and whether it could be saved except by copying the raw packet data. */
2215 void
2216 set_menus_for_capture_file(capture_file *cf)
2217 {
2218   if (cf == NULL) {
2219     /* We have no capture file */
2220     set_menu_sensitivity(main_menu_factory, "/File/Merge...", FALSE);
2221     set_menu_sensitivity(main_menu_factory, "/File/Close", FALSE);
2222     set_menu_sensitivity(main_menu_factory, "/File/Save", FALSE);
2223     set_menu_sensitivity(main_menu_factory, "/File/Save As...", FALSE);
2224     set_menu_sensitivity(main_menu_factory, "/File/Export", FALSE);
2225     set_menu_sensitivity(main_menu_factory, "/View/Reload", FALSE);
2226     set_toolbar_for_capture_file(FALSE);
2227     set_toolbar_for_unsaved_capture_file(FALSE);
2228   } else {
2229     set_menu_sensitivity(main_menu_factory, "/File/Merge...", TRUE);
2230     set_menu_sensitivity(main_menu_factory, "/File/Close", TRUE);
2231     set_menu_sensitivity(main_menu_factory, "/File/Save", !cf->user_saved);
2232     /*
2233      * "Save As..." works only if we can write the file out in at least
2234      * one format (so we can save the whole file or just a subset) or
2235      * if we have an unsaved capture (so writing the whole file out
2236      * with a raw data copy makes sense).
2237      */
2238     set_menu_sensitivity(main_menu_factory, "/File/Save As...",
2239         cf_can_save_as(cf) || !cf->user_saved);
2240     set_menu_sensitivity(main_menu_factory, "/File/Export", TRUE);
2241     set_menu_sensitivity(main_menu_factory, "/View/Reload", TRUE);
2242     set_toolbar_for_unsaved_capture_file(!cf->user_saved);
2243     set_toolbar_for_capture_file(TRUE);
2244   }
2245 }
2246
2247 /* Enable or disable menu items based on whether there's a capture in
2248    progress. */
2249 void
2250 set_menus_for_capture_in_progress(gboolean capture_in_progress)
2251 {
2252   set_menu_sensitivity(main_menu_factory, "/File/Open...",
2253       !capture_in_progress);
2254   set_menu_sensitivity(main_menu_factory, "/File/Open Recent",
2255       !capture_in_progress);
2256   set_menu_sensitivity(main_menu_factory, "/File/Export",
2257        capture_in_progress);
2258 #ifdef HAVE_LIBPCAP
2259   set_menu_sensitivity(main_menu_factory, "/Capture/Options...",
2260       !capture_in_progress);
2261   set_menu_sensitivity(main_menu_factory, "/Capture/Start",
2262       !capture_in_progress);
2263   set_menu_sensitivity(main_menu_factory, "/Capture/Stop",
2264       capture_in_progress);
2265   set_menu_sensitivity(main_menu_factory, "/Capture/Restart",
2266       capture_in_progress);
2267   set_toolbar_for_capture_in_progress(capture_in_progress);
2268
2269   set_capture_if_dialog_for_capture_in_progress(capture_in_progress);
2270 #endif /* HAVE_LIBPCAP */
2271 }
2272
2273 /* Enable or disable menu items based on whether you have some captured
2274    packets. */
2275 static gboolean
2276 walk_menu_tree_for_captured_packets(GList *node,
2277     gboolean have_captured_packets)
2278 {
2279         gboolean    is_enabled;
2280         GList       *child;
2281         menu_item_t *node_data = node->data;
2282
2283         /*
2284          * Is this a leaf node or an interior node?
2285          */
2286         if (node_data->children == NULL) {
2287                 /*
2288                  * It's a leaf node.
2289                  *
2290                  * If it has no "selected_packet_enabled()" or
2291                  * "selected_tree_row_enabled()" routines, we enable
2292                  * it.  This allows tap windows to be popped up even
2293                  * if you have no capture file; this is done to let
2294                  * the user pop up multiple tap windows before reading
2295                  * in a capture file, so that they can be processed in
2296                  * parallel while the capture file is being read rather
2297                  * than one at at time as you pop up the windows, and to
2298                  * let the user pop up tap windows before starting an
2299                  * "Update list of packets in real time" capture, so that
2300                  * the statistics can be displayed while the capture is
2301                  * in progress.
2302                  *
2303                  * If it has either of those routines, we disable it for
2304                  * now - as long as, when a capture is first available,
2305                  * we don't get called after a packet or tree row is
2306                  * selected, that's OK.
2307                  * XXX - that should be done better.
2308                  */
2309                 if (node_data->selected_packet_enabled == NULL &&
2310                     node_data->selected_tree_row_enabled == NULL)
2311                         node_data->enabled = TRUE;
2312                 else
2313                         node_data->enabled = FALSE;
2314         } else {
2315                 /*
2316                  * It's an interior node; call
2317                  * "walk_menu_tree_for_captured_packets()" on all its
2318                  * children and, if any of them are enabled, enable
2319                  * this node, otherwise disable it.
2320                  *
2321                  * XXX - should we just leave all interior nodes enabled?
2322                  * Which is a better UI choice?
2323                  */
2324                 is_enabled = FALSE;
2325                 for (child = node_data->children; child != NULL; child =
2326                     child->next) {
2327                         if (walk_menu_tree_for_captured_packets(child,
2328                             have_captured_packets))
2329                                 is_enabled = TRUE;
2330                 }
2331                 node_data->enabled = is_enabled;
2332         }
2333
2334         /*
2335          * The root node doesn't correspond to a menu tree item; it
2336          * has a null name pointer.
2337          */
2338         if (node_data->name != NULL) {
2339                 set_menu_sensitivity(main_menu_factory, node_data->name,
2340                     node_data->enabled);
2341         }
2342         return node_data->enabled;
2343 }
2344
2345 void
2346 set_menus_for_captured_packets(gboolean have_captured_packets)
2347 {
2348   set_menu_sensitivity(main_menu_factory, "/File/Print...",
2349       have_captured_packets);
2350   set_menu_sensitivity(packet_list_menu_factory, "/Print...",
2351       have_captured_packets);
2352   set_menu_sensitivity(main_menu_factory, "/Edit/Find Packet...",
2353       have_captured_packets);
2354   set_menu_sensitivity(main_menu_factory, "/Edit/Find Next",
2355       have_captured_packets);
2356   set_menu_sensitivity(main_menu_factory, "/Edit/Find Previous",
2357       have_captured_packets);
2358   set_menu_sensitivity(main_menu_factory, "/View/Zoom In",
2359       have_captured_packets);
2360   set_menu_sensitivity(main_menu_factory, "/View/Zoom Out",
2361       have_captured_packets);
2362   set_menu_sensitivity(main_menu_factory, "/View/Normal Size",
2363       have_captured_packets);
2364   set_menu_sensitivity(main_menu_factory, "/Go/Go to Packet...",
2365       have_captured_packets);
2366   set_menu_sensitivity(main_menu_factory, "/Go/Previous Packet",
2367       have_captured_packets);
2368   set_menu_sensitivity(main_menu_factory, "/Go/Next Packet",
2369       have_captured_packets);
2370   set_menu_sensitivity(main_menu_factory, "/Go/First Packet",
2371       have_captured_packets);
2372   set_menu_sensitivity(main_menu_factory, "/Go/Last Packet",
2373       have_captured_packets);
2374   set_menu_sensitivity(main_menu_factory, "/Statistics/Summary",
2375       have_captured_packets);
2376   set_menu_sensitivity(main_menu_factory, "/Statistics/Protocol Hierarchy",
2377       have_captured_packets);
2378
2379   walk_menu_tree_for_captured_packets(tap_menu_tree_root,
2380       have_captured_packets);
2381   set_toolbar_for_captured_packets(have_captured_packets);
2382 }
2383
2384 /* Enable or disable menu items based on whether a packet is selected and,
2385    if so, on the properties of the packet. */
2386 static gboolean
2387 walk_menu_tree_for_selected_packet(GList *node, frame_data *fd,
2388     epan_dissect_t *edt)
2389 {
2390         gboolean is_enabled;
2391         GList *child;
2392         menu_item_t *node_data = node->data;
2393
2394         /*
2395          * Is this a leaf node or an interior node?
2396          */
2397         if (node_data->children == NULL) {
2398                 /*
2399                  * It's a leaf node.
2400                  *
2401                  * If it has no "selected_packet_enabled()" routine,
2402                  * leave its enabled/disabled status alone - it
2403                  * doesn't depend on whether we have a packet selected
2404                  * or not or on the selected packet.
2405                  *
2406                  * If it has a "selected_packet_enabled()" routine,
2407                  * call it and set the item's enabled/disabled status
2408                  * based on its return value.
2409                  */
2410                 if (node_data->selected_packet_enabled != NULL)
2411                         node_data->enabled = node_data->selected_packet_enabled(fd, edt, node_data->callback_data);
2412         } else {
2413                 /*
2414                  * It's an interior node; call
2415                  * "walk_menu_tree_for_selected_packet()" on all its
2416                  * children and, if any of them are enabled, enable
2417                  * this node, otherwise disable it.
2418                  *
2419                  * XXX - should we just leave all interior nodes enabled?
2420                  * Which is a better UI choice?
2421                  */
2422                 is_enabled = FALSE;
2423                 for (child = node_data->children; child != NULL; child =
2424                     child->next) {
2425                         if (walk_menu_tree_for_selected_packet(child, fd, edt))
2426                                 is_enabled = TRUE;
2427                 }
2428                 node_data->enabled = is_enabled;
2429         }
2430
2431         /*
2432          * The root node doesn't correspond to a menu tree item; it
2433          * has a null name pointer.
2434          */
2435         if (node_data->name != NULL) {
2436                 set_menu_sensitivity(main_menu_factory, node_data->name,
2437                     node_data->enabled);
2438         }
2439         return node_data->enabled;
2440 }
2441
2442 gboolean
2443 packet_is_ssl(epan_dissect_t* edt)
2444 {
2445   GPtrArray* array;
2446   int ssl_id;
2447   gboolean is_ssl;
2448
2449   if (!edt || !edt->tree)
2450       return FALSE;
2451   ssl_id = proto_get_id_by_filter_name("ssl");
2452   if (ssl_id < 0)
2453       return FALSE;
2454   array = proto_find_finfo(edt->tree, ssl_id);
2455   is_ssl = (array->len > 0) ? TRUE : FALSE;
2456   g_ptr_array_free(array, FALSE);
2457   return is_ssl;
2458 }
2459
2460 void
2461 set_menus_for_selected_packet(capture_file *cf)
2462 {
2463   gboolean is_ssl = packet_is_ssl(cf->edt);
2464   set_menu_sensitivity(main_menu_factory, "/Edit/Mark Packet (toggle)",
2465       cf->current_frame != NULL);
2466   set_menu_sensitivity(packet_list_menu_factory, "/Mark Packet (toggle)",
2467       cf->current_frame != NULL);
2468   set_menu_sensitivity(main_menu_factory, "/Edit/Find Next Mark",
2469       cf->current_frame != NULL);
2470   set_menu_sensitivity(main_menu_factory, "/Edit/Find Previous Mark",
2471       cf->current_frame != NULL);
2472   set_menu_sensitivity(main_menu_factory, "/Edit/Mark All Packets",
2473       cf->current_frame != NULL);
2474   set_menu_sensitivity(main_menu_factory, "/Edit/Unmark All Packets",
2475       cf->current_frame != NULL);
2476   set_menu_sensitivity(main_menu_factory, "/Edit/Set Time Reference (toggle)",
2477       cf->current_frame != NULL);
2478   set_menu_sensitivity(packet_list_menu_factory, "/Set Time Reference (toggle)",
2479       cf->current_frame != NULL);
2480   set_menu_sensitivity(main_menu_factory, "/Edit/Find Next Reference",
2481       cf->current_frame != NULL);
2482   set_menu_sensitivity(main_menu_factory, "/Edit/Find Previous Reference",
2483       cf->current_frame != NULL);
2484   set_menu_sensitivity(main_menu_factory, "/View/Resize All Columns",
2485       cf->current_frame != NULL);
2486   set_menu_sensitivity(main_menu_factory, "/View/Collapse All",
2487       cf->current_frame != NULL);
2488   set_menu_sensitivity(tree_view_menu_factory, "/Collapse All",
2489       cf->current_frame != NULL);
2490   set_menu_sensitivity(main_menu_factory, "/View/Expand All",
2491       cf->current_frame != NULL);
2492   set_menu_sensitivity(tree_view_menu_factory, "/Expand All",
2493       cf->current_frame != NULL);
2494   set_menu_sensitivity(main_menu_factory, "/View/Colorize Conversation",
2495       cf->current_frame != NULL);
2496   set_menu_sensitivity(main_menu_factory, "/View/Reset Coloring 1-10",
2497       tmp_color_filters_used());
2498   set_menu_sensitivity(main_menu_factory, "/View/Show Packet in New Window",
2499       cf->current_frame != NULL);
2500   set_menu_sensitivity(packet_list_menu_factory, "/Show Packet in New Window",
2501       cf->current_frame != NULL);
2502   set_menu_sensitivity(packet_list_menu_factory, "/SCTP",
2503       cf->current_frame != NULL ? (cf->edt->pi.ipproto == IP_PROTO_SCTP) : FALSE);
2504   set_menu_sensitivity(main_menu_factory, "/Analyze/Follow TCP Stream",
2505       cf->current_frame != NULL ? (cf->edt->pi.ipproto == IP_PROTO_TCP) : FALSE);
2506   set_menu_sensitivity(packet_list_menu_factory, "/Follow TCP Stream",
2507       cf->current_frame != NULL ? (cf->edt->pi.ipproto == IP_PROTO_TCP) : FALSE);
2508   set_menu_sensitivity(tree_view_menu_factory, "/Follow TCP Stream",
2509       cf->current_frame != NULL ? (cf->edt->pi.ipproto == IP_PROTO_TCP) : FALSE);
2510   set_menu_sensitivity(main_menu_factory, "/Analyze/Follow UDP Stream",
2511       cf->current_frame != NULL ? (cf->edt->pi.ipproto == IP_PROTO_UDP) : FALSE);
2512   set_menu_sensitivity(packet_list_menu_factory, "/Follow UDP Stream",
2513       cf->current_frame != NULL ? (cf->edt->pi.ipproto == IP_PROTO_UDP) : FALSE);
2514   set_menu_sensitivity(tree_view_menu_factory, "/Follow UDP Stream",
2515       cf->current_frame != NULL ? (cf->edt->pi.ipproto == IP_PROTO_UDP) : FALSE);
2516   set_menu_sensitivity(main_menu_factory, "/Analyze/Follow SSL Stream",
2517       cf->current_frame != NULL ? is_ssl : FALSE);
2518   set_menu_sensitivity(packet_list_menu_factory, "/Follow SSL Stream",
2519       cf->current_frame != NULL ? is_ssl : FALSE);
2520   set_menu_sensitivity(tree_view_menu_factory, "/Follow SSL Stream",
2521       cf->current_frame != NULL ? is_ssl : FALSE);
2522   set_menu_sensitivity(packet_list_menu_factory, "/Conversation Filter",
2523       cf->current_frame != NULL);
2524   set_menu_sensitivity(packet_list_menu_factory, "/Conversation Filter/Ethernet",
2525       cf->current_frame != NULL ? (cf->edt->pi.dl_src.type == 1) : FALSE);
2526   set_menu_sensitivity(packet_list_menu_factory, "/Conversation Filter/IP",
2527       cf->current_frame != NULL ? (cf->edt->pi.ethertype == 0x800) : FALSE);
2528   set_menu_sensitivity(packet_list_menu_factory, "/Conversation Filter/TCP",
2529       cf->current_frame != NULL ? (cf->edt->pi.ipproto == IP_PROTO_TCP) : FALSE);
2530   set_menu_sensitivity(packet_list_menu_factory, "/Conversation Filter/UDP",
2531       cf->current_frame != NULL ? (cf->edt->pi.ipproto == IP_PROTO_UDP) : FALSE);
2532   set_menu_sensitivity(packet_list_menu_factory, "/Conversation Filter/PN-CBA Server",
2533       cf->current_frame != NULL ? (cf->edt->pi.profinet_type != 0 && cf->edt->pi.profinet_type < 10) : FALSE);
2534   set_menu_sensitivity(packet_list_menu_factory, "/Colorize Conversation",
2535       cf->current_frame != NULL);
2536   set_menu_sensitivity(packet_list_menu_factory, "/Colorize Conversation/Ethernet",
2537       cf->current_frame != NULL ? (cf->edt->pi.dl_src.type == 1) : FALSE);
2538   set_menu_sensitivity(packet_list_menu_factory, "/Colorize Conversation/IP",
2539       cf->current_frame != NULL ? (cf->edt->pi.ethertype == 0x800) : FALSE);
2540   set_menu_sensitivity(packet_list_menu_factory, "/Colorize Conversation/TCP",
2541       cf->current_frame != NULL ? (cf->edt->pi.ipproto == IP_PROTO_TCP) : FALSE);
2542   set_menu_sensitivity(packet_list_menu_factory, "/Colorize Conversation/UDP",
2543       cf->current_frame != NULL ? (cf->edt->pi.ipproto == IP_PROTO_UDP) : FALSE);
2544   set_menu_sensitivity(packet_list_menu_factory, "/Colorize Conversation/PN-CBA Server",
2545       cf->current_frame != NULL ? (cf->edt->pi.profinet_type != 0 && cf->edt->pi.profinet_type < 10) : FALSE);
2546   set_menu_sensitivity(main_menu_factory, "/Analyze/Decode As...",
2547       cf->current_frame != NULL && decode_as_ok());
2548   set_menu_sensitivity(packet_list_menu_factory, "/Decode As...",
2549       cf->current_frame != NULL && decode_as_ok());
2550   set_menu_sensitivity(tree_view_menu_factory, "/Decode As...",
2551       cf->current_frame != NULL && decode_as_ok());
2552   set_menu_sensitivity(main_menu_factory, "/View/Name Resolution/Resolve Name",
2553       cf->current_frame != NULL && (g_resolv_flags & RESOLV_ALL_ADDRS) != RESOLV_ALL_ADDRS);
2554   set_menu_sensitivity(tree_view_menu_factory, "/Resolve Name",
2555       cf->current_frame != NULL && (g_resolv_flags & RESOLV_ALL_ADDRS) != RESOLV_ALL_ADDRS);
2556   set_menu_sensitivity(packet_list_menu_factory, "/Copy",
2557       cf->current_frame != NULL);
2558   set_menu_sensitivity(packet_list_menu_factory, "/Apply as Filter",
2559       cf->current_frame != NULL);
2560   set_menu_sensitivity(packet_list_menu_factory, "/Prepare a Filter",
2561       cf->current_frame != NULL);
2562   set_menu_sensitivity(main_menu_factory, "/Tools/Firewall ACL Rules",
2563       cf->current_frame != NULL);
2564
2565   walk_menu_tree_for_selected_packet(tap_menu_tree_root, cf->current_frame,
2566       cf->edt);
2567 }
2568
2569 /* Enable or disable menu items based on whether a tree row is selected
2570    and, if so, on the properties of the tree row. */
2571 static gboolean
2572 walk_menu_tree_for_selected_tree_row(GList *node, field_info *fi)
2573 {
2574         gboolean is_enabled;
2575         GList *child;
2576         menu_item_t *node_data = node->data;
2577
2578         /*
2579          * Is this a leaf node or an interior node?
2580          */
2581         if (node_data->children == NULL) {
2582                 /*
2583                  * It's a leaf node.
2584                  *
2585                  * If it has no "selected_tree_row_enabled()" routine,
2586                  * leave its enabled/disabled status alone - it
2587                  * doesn't depend on whether we have a tree row selected
2588                  * or not or on the selected tree row.
2589                  *
2590                  * If it has a "selected_tree_row_enabled()" routine,
2591                  * call it and set the item's enabled/disabled status
2592                  * based on its return value.
2593                  */
2594                 if (node_data->selected_tree_row_enabled != NULL)
2595                         node_data->enabled = node_data->selected_tree_row_enabled(fi, node_data->callback_data);
2596         } else {
2597                 /*
2598                  * It's an interior node; call
2599                  * "walk_menu_tree_for_selected_tree_row()" on all its
2600                  * children and, if any of them are enabled, enable
2601                  * this node, otherwise disable it.
2602                  *
2603                  * XXX - should we just leave all interior nodes enabled?
2604                  * Which is a better UI choice?
2605                  */
2606                 is_enabled = FALSE;
2607                 for (child = node_data->children; child != NULL; child =
2608                     child->next) {
2609                         if (walk_menu_tree_for_selected_tree_row(child, fi))
2610                                 is_enabled = TRUE;
2611                 }
2612                 node_data->enabled = is_enabled;
2613         }
2614
2615         /*
2616          * The root node doesn't correspond to a menu tree item; it
2617          * has a null name pointer.
2618          */
2619         if (node_data->name != NULL) {
2620                 set_menu_sensitivity(main_menu_factory, node_data->name,
2621                     node_data->enabled);
2622         }
2623         return node_data->enabled;
2624 }
2625
2626 void
2627 set_menus_for_selected_tree_row(capture_file *cf)
2628 {
2629   gboolean properties;
2630   gint id;
2631
2632   if (cf->finfo_selected != NULL) {
2633         header_field_info *hfinfo = cf->finfo_selected->hfinfo;
2634         if (hfinfo->parent == -1) {
2635           properties = prefs_is_registered_protocol(hfinfo->abbrev);
2636           id = (hfinfo->type == FT_PROTOCOL) ? proto_get_id((protocol_t *)hfinfo->strings) : -1;
2637         } else {
2638           properties = prefs_is_registered_protocol(proto_registrar_get_abbrev(hfinfo->parent));
2639           id = hfinfo->parent;
2640         }
2641         set_menu_sensitivity(main_menu_factory,
2642           "/File/Export/Selected Packet Bytes...", TRUE);
2643         set_menu_sensitivity(main_menu_factory,
2644           "/Go/Go to Corresponding Packet", hfinfo->type == FT_FRAMENUM);
2645         set_menu_sensitivity(tree_view_menu_factory,
2646           "/Go to Corresponding Packet", hfinfo->type == FT_FRAMENUM);
2647         set_menu_sensitivity(main_menu_factory, "/Edit/Copy",
2648           proto_can_match_selected(cf->finfo_selected, cf->edt));
2649         set_menu_sensitivity(tree_view_menu_factory, "/Copy",
2650           TRUE);
2651         set_menu_sensitivity(tree_view_menu_factory, "/Copy/As Filter",
2652           proto_can_match_selected(cf->finfo_selected, cf->edt));
2653         set_menu_sensitivity(main_menu_factory, "/Analyze/Apply as Filter",
2654           proto_can_match_selected(cf->finfo_selected, cf->edt));
2655         set_menu_sensitivity(tree_view_menu_factory, "/Apply as Filter",
2656           proto_can_match_selected(cf->finfo_selected, cf->edt));
2657         set_menu_sensitivity(main_menu_factory, "/Analyze/Prepare a Filter",
2658           proto_can_match_selected(cf->finfo_selected, cf->edt));
2659         set_menu_sensitivity(tree_view_menu_factory, "/Prepare a Filter",
2660           proto_can_match_selected(cf->finfo_selected, cf->edt));
2661         set_menu_sensitivity(tree_view_menu_factory, "/Colorize with Filter",
2662           proto_can_match_selected(cf->finfo_selected, cf->edt));
2663         set_menu_sensitivity(tree_view_menu_factory, "/Protocol Preferences...",
2664           properties);
2665         set_menu_sensitivity(tree_view_menu_factory, "/Disable Protocol...",
2666           (id == -1) ? FALSE : proto_can_toggle_protocol(id));
2667         set_menu_sensitivity(main_menu_factory, "/View/Expand Subtrees", cf->finfo_selected->tree_type != -1);
2668         set_menu_sensitivity(tree_view_menu_factory, "/Expand Subtrees", cf->finfo_selected->tree_type != -1);
2669         set_menu_sensitivity(tree_view_menu_factory, "/Wiki Protocol Page",
2670           TRUE);
2671         set_menu_sensitivity(tree_view_menu_factory, "/Filter Field Reference",
2672           TRUE);
2673   } else {
2674         set_menu_sensitivity(main_menu_factory,
2675           "/File/Export/Selected Packet Bytes...", FALSE);
2676         set_menu_sensitivity(main_menu_factory,
2677           "/Go/Go to Corresponding Packet", FALSE);
2678         set_menu_sensitivity(tree_view_menu_factory,
2679           "/Go to Corresponding Packet", FALSE);
2680         set_menu_sensitivity(main_menu_factory, "/Edit/Copy", FALSE);
2681         set_menu_sensitivity(tree_view_menu_factory, "/Copy", FALSE);
2682         set_menu_sensitivity(main_menu_factory, "/Analyze/Apply as Filter", FALSE);
2683         set_menu_sensitivity(tree_view_menu_factory, "/Apply as Filter", FALSE);
2684         set_menu_sensitivity(main_menu_factory, "/Analyze/Prepare a Filter", FALSE);
2685         set_menu_sensitivity(tree_view_menu_factory, "/Prepare a Filter", FALSE);
2686         set_menu_sensitivity(tree_view_menu_factory, "/Colorize with Filter", FALSE);
2687         set_menu_sensitivity(tree_view_menu_factory, "/Protocol Preferences...",
2688           FALSE);
2689         set_menu_sensitivity(tree_view_menu_factory, "/Disable Protocol...", FALSE);
2690         set_menu_sensitivity(main_menu_factory, "/View/Expand Subtrees", FALSE);
2691         set_menu_sensitivity(tree_view_menu_factory, "/Expand Subtrees", FALSE);
2692         set_menu_sensitivity(tree_view_menu_factory, "/Wiki Protocol Page",
2693           FALSE);
2694         set_menu_sensitivity(tree_view_menu_factory, "/Filter Field Reference",
2695           FALSE);
2696   }
2697
2698   walk_menu_tree_for_selected_tree_row(tap_menu_tree_root, cf->finfo_selected);
2699 }
2700
2701 void set_menus_for_packet_history(gboolean back_history, gboolean forward_history) {
2702
2703   set_menu_sensitivity(main_menu_factory, "/Go/Back", back_history);
2704   set_menu_sensitivity(main_menu_factory, "/Go/Forward", forward_history);
2705
2706   set_toolbar_for_packet_history(back_history, forward_history);
2707 }
2708
2709
2710 void set_menus_for_file_set(gboolean file_set, gboolean previous_file, gboolean next_file) {
2711
2712   set_menu_sensitivity(main_menu_factory, "/File/File Set/List Files", file_set);
2713   set_menu_sensitivity(main_menu_factory, "/File/File Set/Previous File", previous_file);
2714   set_menu_sensitivity(main_menu_factory, "/File/File Set/Next File", next_file);
2715 }