Fix for bug 2964.
[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 #include "gtk/main_welcome.h"
91
92
93 typedef struct _menu_item {
94     char    *name;
95     gint    group;
96     const char *stock_id;
97     gboolean enabled;
98     GtkItemFactoryCallback callback;
99     gpointer callback_data;
100     gboolean (*selected_packet_enabled)(frame_data *, epan_dissect_t *, gpointer callback_data);
101     gboolean (*selected_tree_row_enabled)(field_info *, gpointer callback_data);
102     GList *children;
103 } menu_item_t;
104
105 static GList *tap_menu_tree_root = NULL;
106
107 GtkWidget *popup_menu_object;
108
109
110 #define GTK_MENU_FUNC(a) ((GtkItemFactoryCallback)(a))
111
112 static void merge_all_tap_menus(GList *node);
113 static void clear_menu_recent_capture_file_cmd_cb(GtkWidget *w, gpointer unused _U_);
114
115 static void menus_init(void);
116 static void set_menu_sensitivity (GtkItemFactory *, const gchar *, gint);
117 static void show_hide_cb(GtkWidget *w, gpointer data, gint action);
118 static void timestamp_format_cb(GtkWidget *w, gpointer d, gint action);
119 static void timestamp_precision_cb(GtkWidget *w, gpointer d, gint action);
120 static void name_resolution_cb(GtkWidget *w, gpointer d, gint action);
121 #ifdef HAVE_LIBPCAP
122 static void auto_scroll_live_cb(GtkWidget *w, gpointer d);
123 #endif
124 static void colorize_cb(GtkWidget *w, gpointer d);
125
126
127 /* This is the GtkItemFactoryEntry structure used to generate new menus.
128        Item 1: The menu path. The letter after the underscore indicates an
129                accelerator key once the menu is open.
130        Item 2: The accelerator key for the entry
131        Item 3: The callback function.
132        Item 4: The callback action.  This changes the parameters with
133                which the function is called.  The default is 0.
134        Item 5: The item type, used to define what kind of an item it is.
135                Here are the possible values:
136
137                NULL               -> "<Item>"
138                ""                 -> "<Item>"
139                "<Title>"          -> create a title item
140                "<Item>"           -> create a simple item
141                "<ImageItem>"      -> create an item holding an image (gtk2)
142                "<StockItem>"      -> create an item holding a stock image (gtk2)
143                "<CheckItem>"      -> create a check item
144                "<ToggleItem>"     -> create a toggle item
145                "<RadioItem>"      -> create a radio item
146                <path>             -> path of a radio item to link against
147                "<Separator>"      -> create a separator
148                "<Tearoff>"        -> create a tearoff separator (gtk2)
149                "<Branch>"         -> create an item to hold sub items (optional)
150                "<LastBranch>"     -> create a right justified branch
151        Item 6: extra data needed for ImageItem and StockItem (gtk2)
152     */
153
154 /*  As a general GUI guideline, we try to follow the Gnome Human Interface Guidelines, which can be found at:
155     http://developer.gnome.org/projects/gup/hig/1.0/index.html
156
157 Please note: there are some differences between the Gnome HIG menu suggestions and our implementation:
158
159 File/Open Recent:   the Gnome HIG suggests putting the list of recently used files as elements into the File menuitem.
160                     As this is ok for only a few items, this will become unhandy for 10 or even more list entries.
161                     For this reason, we use a submenu for this.
162
163 File/Close:         the Gnome HIG suggests putting this item just above the Quit item.
164                     This results in unintuitive behaviour as both Close and Quit items are very near together.
165                     By putting the Close item near the open item(s), it better suggests that it will close the
166                     currently opened/captured file only.
167 */
168
169 typedef enum {
170     SHOW_HIDE_MAIN_TOOLBAR = 1,
171     SHOW_HIDE_FILTER_TOOLBAR,
172     SHOW_HIDE_AIRPCAP_TOOLBAR,
173     SHOW_HIDE_STATUSBAR,
174     SHOW_HIDE_PACKET_LIST,
175     SHOW_HIDE_TREE_VIEW,
176     SHOW_HIDE_BYTE_VIEW
177 } show_hide_values_e;
178
179 typedef enum {
180     CONV_ETHER = 1,
181     CONV_IP,
182     CONV_TCP,
183     CONV_UDP,
184     CONV_CBA
185 } conv_values_e;
186
187 char *
188 build_conversation_filter(int action, gboolean show_dialog)
189 {
190     packet_info *pi = &cfile.edt->pi;
191     char        *buf;
192
193
194     switch(action) {
195     case(CONV_CBA):
196         if (pi->profinet_type == 0) {
197             if (show_dialog) {
198                 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
199                     "Error filtering conversation.  Please make\n"
200                     "sure you have a PROFINET CBA packet selected.");
201             }
202             return NULL;
203         }
204
205         if( pi->net_src.type == AT_IPv4 && pi->net_dst.type == AT_IPv4
206         && pi->ipproto == 6 ) {
207             /* IPv4 */
208             switch(pi->profinet_type) {
209             case(1):
210                 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)",
211                     ip_to_str( pi->net_dst.data),
212                     ip_to_str( pi->net_src.data),
213                     ip_to_str( pi->net_src.data),
214                     ip_to_str( pi->net_dst.data));
215                 break;
216             case(2):
217                 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)",
218                     ip_to_str( pi->net_src.data),
219                     ip_to_str( pi->net_dst.data),
220                     ip_to_str( pi->net_dst.data),
221                     ip_to_str( pi->net_src.data));
222                 break;
223             case(3):
224                 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)",
225                     ip_to_str( pi->net_dst.data),
226                     ip_to_str( pi->net_src.data),
227                     ip_to_str( pi->net_src.data),
228                     ip_to_str( pi->net_dst.data));
229                 break;
230             case(4):
231                 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)",
232                     ip_to_str( pi->net_src.data),
233                     ip_to_str( pi->net_dst.data),
234                     ip_to_str( pi->net_dst.data),
235                     ip_to_str( pi->net_src.data));
236                 break;
237             default:
238                 return NULL;
239             }
240         } else {
241             return NULL;
242         }
243         break;
244     case(CONV_TCP):
245         if (cfile.edt->pi.ipproto != IP_PROTO_TCP) {
246             if (show_dialog) {
247                 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
248                     "Error filtering conversation.  Please make\n"
249                     "sure you have a TCP packet selected.");
250             }
251             return NULL;
252         }
253
254         if( pi->net_src.type == AT_IPv4 && pi->net_dst.type == AT_IPv4
255         && pi->ipproto == 6 ) {
256             /* TCP over IPv4 */
257             buf = g_strdup_printf("(ip.addr eq %s and ip.addr eq %s) and (tcp.port eq %d and tcp.port eq %d)",
258                 ip_to_str( pi->net_src.data),
259                 ip_to_str( pi->net_dst.data),
260                 pi->srcport, pi->destport );
261         } else if( pi->net_src.type == AT_IPv6 && pi->net_dst.type == AT_IPv6
262                 && pi->ipproto == 6 ) {
263             /* TCP over IPv6 */
264             buf = g_strdup_printf("(ipv6.addr eq %s and ipv6.addr eq %s) and (tcp.port eq %d and tcp.port eq %d)",
265                 ip6_to_str((const struct e_in6_addr *)pi->net_src.data),
266                 ip6_to_str((const struct e_in6_addr *)pi->net_dst.data),
267                 pi->srcport, pi->destport );
268         } else {
269             return NULL;
270         }
271         break;
272     case(CONV_UDP):
273         if (cfile.edt->pi.ipproto != IP_PROTO_UDP) {
274             if (show_dialog) {
275                 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
276                     "Error filtering conversation.  Please make\n"
277                     "sure you have a UDP packet selected.");
278             }
279             return NULL;
280         }
281
282         if( pi->net_src.type == AT_IPv4 && pi->net_dst.type == AT_IPv4
283         && pi->ipproto == IP_PROTO_UDP /*6*/ ) {
284             /* UDP over IPv4 */
285             buf = g_strdup_printf("(ip.addr eq %s and ip.addr eq %s) and (udp.port eq %d and udp.port eq %d)",
286                 ip_to_str( pi->net_src.data),
287                 ip_to_str( pi->net_dst.data),
288                 pi->srcport, pi->destport );
289         } else if( pi->net_src.type == AT_IPv6 && pi->net_dst.type == AT_IPv6
290                 && pi->ipproto == IP_PROTO_UDP /*6*/ ) {
291             /* UDP over IPv6 */
292             buf = g_strdup_printf("(ipv6.addr eq %s and ipv6.addr eq %s) and (udp.port eq %d and udp.port eq %d)",
293                 ip6_to_str((const struct e_in6_addr *)pi->net_src.data),
294                 ip6_to_str((const struct e_in6_addr *)pi->net_dst.data),
295                 pi->srcport, pi->destport );
296         } else {
297             return NULL;
298         }
299         break;
300     case(CONV_IP):
301         if (cfile.edt->pi.ethertype != 0x800) {
302             if (show_dialog) {
303                 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
304                     "Error filtering conversation.  Please make\n"
305                     "sure you have a IP packet selected.");
306             }
307             return NULL;
308         }
309
310         if( pi->net_src.type == AT_IPv4 && pi->net_dst.type == AT_IPv4
311         && pi->ipproto == 6 ) {
312             /* IPv4 */
313             buf = g_strdup_printf("ip.addr eq %s and ip.addr eq %s",
314                 ip_to_str( pi->net_src.data),
315                 ip_to_str( pi->net_dst.data));
316         } else if( pi->net_src.type == AT_IPv6 && pi->net_dst.type == AT_IPv6
317                 && pi->ipproto == 6 ) {
318             /* IPv6 */
319             buf = g_strdup_printf("ipv6.addr eq %s and ipv6.addr eq %s",
320                 ip6_to_str((const struct e_in6_addr *)pi->net_src.data),
321                 ip6_to_str((const struct e_in6_addr *)pi->net_dst.data));
322         } else {
323             return NULL;
324         }
325         break;
326     case(CONV_ETHER):
327         /* XXX - is this the right way to check for Ethernet? */
328         /* check for the data link address type */
329         /* (ethertype will be 0 when used as length field) */
330         if (cfile.edt->pi.dl_src.type != 1) {
331             if (show_dialog) {
332                 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
333                     "Error filtering conversation.  Please make\n"
334                     "sure you have a Ethernet packet selected.");
335             }
336             return NULL;
337         }
338
339         if( pi->dl_src.type == 1 /*AT_IPv4*/ && pi->dl_dst.type == 1 /*AT_IPv4*/) {
340             /* Ethernet */
341             buf = g_strdup_printf("eth.addr eq %s and eth.addr eq %s",
342                 ether_to_str( pi->dl_src.data),
343                 ether_to_str( pi->dl_dst.data));
344         } else {
345             return NULL;
346         }
347         break;
348     default:
349         return NULL;
350     }
351
352     return buf;
353 }
354
355 void
356 conversation_cb(GtkWidget * w, gpointer data _U_, int action)
357 {
358     gchar       *filter;
359     GtkWidget   *filter_te;
360
361     if (cfile.current_frame) {
362         /* create a filter-string based on the selected packet and action */
363         filter = build_conversation_filter(action, TRUE);
364
365         /* Run the display filter so it goes in effect - even if it's the
366         same as the previous display filter. */
367         filter_te = g_object_get_data(G_OBJECT(w), E_DFILTER_TE_KEY);
368         gtk_entry_set_text(GTK_ENTRY(filter_te), filter);
369         main_filter_packets(&cfile, filter, TRUE);
370
371         g_free(filter);
372     }
373 }
374
375 void
376 colorize_conversation_cb(GtkWidget * w _U_, gpointer data _U_, int action)
377 {
378     gchar        *filter = NULL;
379
380     if( (action>>8) == 255 ) {
381         color_filters_reset_tmp();
382         cf_colorize_packets(&cfile);
383     } else if (cfile.current_frame) {
384         if( (action&0xff) == 0 ) {
385             /* colorize_conversation_cb was called from the window-menu
386              * or through an accelerator key. Try to build a conversation
387              * filter in the order TCP, UDP, IP, Ethernet and apply the
388              * coloring */
389             filter = build_conversation_filter(CONV_TCP,FALSE);
390             if( filter == NULL )
391                 filter = build_conversation_filter(CONV_UDP,FALSE);
392             if( filter == NULL )
393                 filter = build_conversation_filter(CONV_IP,FALSE);
394             if( filter == NULL )
395                 filter = build_conversation_filter(CONV_ETHER,FALSE);
396             if( filter == NULL ) {
397                 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Unable to build conversation filter.");
398                 return;
399             }
400         } else {
401             /* create a filter-string based on the selected packet and action */
402             filter = build_conversation_filter(action&0xff, TRUE);
403         }
404
405         if( (action>>8) == 0) {
406             /* Open the "new coloring filter" dialog with the filter */
407             color_display_with_filter(filter);
408         } else {
409             /* Set one of the temporary coloring filters */
410             color_filters_set_tmp((guint8)(action>>8),filter,FALSE);
411             cf_colorize_packets(&cfile);
412         }
413
414         g_free(filter);
415     }
416 }
417
418 /* main menu */
419 static GtkItemFactoryEntry menu_items[] =
420 {
421     {"/_File", NULL, NULL, 0, "<Branch>", NULL,},
422     {"/File/_Open...", "<control>O", GTK_MENU_FUNC(file_open_cmd_cb),
423                              0, "<StockItem>", GTK_STOCK_OPEN,},
424     {"/File/Open _Recent", NULL, NULL, 0, "<Branch>", NULL,},
425     {"/File/_Merge...", NULL, GTK_MENU_FUNC(file_merge_cmd_cb), 0, NULL, NULL,},
426     {"/File/_Close", "<control>W", GTK_MENU_FUNC(file_close_cmd_cb),
427                              0, "<StockItem>", GTK_STOCK_CLOSE,},
428     {"/File/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
429     {"/File/_Save", "<control>S", GTK_MENU_FUNC(file_save_cmd_cb),
430                              0, "<StockItem>", GTK_STOCK_SAVE,},
431     {"/File/Save _As...", "<shift><control>S", GTK_MENU_FUNC(file_save_as_cmd_cb),
432                              0, "<StockItem>", GTK_STOCK_SAVE_AS,},
433     {"/File/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
434     {"/File/File Set", NULL, NULL, 0, "<Branch>", NULL,},
435     {"/File/File Set/List Files", NULL, GTK_MENU_FUNC(fileset_cb), 0, "<StockItem>", WIRESHARK_STOCK_FILE_SET_LIST,},
436     {"/File/File Set/Next File", NULL, GTK_MENU_FUNC(fileset_next_cb), 0, "<StockItem>", WIRESHARK_STOCK_FILE_SET_NEXT,},
437     {"/File/File Set/Previous File", NULL, GTK_MENU_FUNC(fileset_previous_cb), 0, "<StockItem>", WIRESHARK_STOCK_FILE_SET_PREVIOUS,},
438     {"/File/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
439     {"/File/_Export", NULL, NULL, 0, "<Branch>", NULL,},
440 #if _WIN32
441     {"/File/Export/File...", NULL, GTK_MENU_FUNC(export_text_cmd_cb),
442                          0, NULL, NULL,},
443 #else
444     {"/File/Export/as \"Plain _Text\" file...", NULL, GTK_MENU_FUNC(export_text_cmd_cb),
445                              0, NULL, NULL,},
446     {"/File/Export/as \"_PostScript\" file...", NULL, GTK_MENU_FUNC(export_ps_cmd_cb),
447                              0, NULL, NULL,},
448     {"/File/Export/as \"_CSV\" (Comma Separated Values packet summary) file...",
449                              NULL, GTK_MENU_FUNC(export_csv_cmd_cb), 0, NULL, NULL,},
450     {"/File/Export/as \"C _Arrays\" (packet bytes) file...", NULL, GTK_MENU_FUNC(export_carrays_cmd_cb),
451                              0, NULL, NULL,},
452     {"/File/Export/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
453     {"/File/Export/as XML - \"P_SML\" (packet summary) file...", NULL, GTK_MENU_FUNC(export_psml_cmd_cb),
454                              0, NULL, NULL,},
455     {"/File/Export/as XML - \"P_DML\" (packet details) file...", NULL, GTK_MENU_FUNC(export_pdml_cmd_cb),
456                              0, NULL, NULL,},
457     {"/File/Export/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
458 #endif
459     {"/File/Export/Selected Packet _Bytes...", "<control>H", GTK_MENU_FUNC(savehex_cb),
460                              0, NULL, NULL,},
461     {"/File/Export/_Objects/_HTTP", NULL, GTK_MENU_FUNC(eo_http_cb), 0, NULL, NULL,},
462     {"/File/Export/_Objects/_DICOM", NULL, GTK_MENU_FUNC(eo_dicom_cb), 0, NULL, NULL,},
463
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", "<control>A", GTK_MENU_FUNC(packet_list_mark_all_frames_cb),
496                        0, NULL, NULL,},
497     {"/Edit/_Unmark All Packets", "<control>D", 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", "<alt><shift><control>N", GTK_MENU_FUNC(reftime_frame_cb), REFTIME_FIND_NEXT, NULL, NULL,},
503     {"/Edit/Find Previous Reference", "<alt><shift><control>B", 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/FAQ's", NULL, GTK_MENU_FUNC(topic_menu_cb), ONLINEPAGE_FAQ, 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/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
713     {"/Help/Website", NULL, GTK_MENU_FUNC(topic_menu_cb), ONLINEPAGE_HOME, "<StockItem>", GTK_STOCK_HOME,},
714     {"/Help/Wiki", NULL, GTK_MENU_FUNC(topic_menu_cb), ONLINEPAGE_WIKI, "<StockItem>", WIRESHARK_STOCK_WIKI,},
715     {"/Help/Downloads", NULL, GTK_MENU_FUNC(topic_menu_cb), ONLINEPAGE_DOWNLOAD, NULL, NULL,},
716     {"/Help/Sample Captures", NULL, GTK_MENU_FUNC(topic_menu_cb), ONLINEPAGE_SAMPLE_FILES, NULL, NULL,},
717     {"/Help/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
718     {"/Help/_Supported Protocols (slow!)", NULL, GTK_MENU_FUNC(supported_cb), 0, 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     {"/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
933
934     {"/Decode As...", NULL, GTK_MENU_FUNC(decode_as_cb), 0, "<StockItem>", WIRESHARK_STOCK_DECODE_AS,},
935     {"/Print...", NULL, GTK_MENU_FUNC(file_print_selected_cmd_cb), 0, "<StockItem>", GTK_STOCK_PRINT,},
936     {"/Show Packet in New Window", NULL, GTK_MENU_FUNC(new_window_cb),
937                        0, NULL, NULL}
938 };
939
940 static GtkItemFactoryEntry tree_view_menu_items[] =
941 {
942
943     {"/Expand Subtrees", NULL, GTK_MENU_FUNC(expand_tree_cb), 0, NULL, NULL,},
944     {"/Expand All", NULL, GTK_MENU_FUNC(expand_all_cb), 0, NULL, NULL,},
945     {"/Collapse All", NULL, GTK_MENU_FUNC(collapse_all_cb), 0, NULL, NULL,},
946
947     {"/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
948
949     {"/Apply as Filter", NULL, NULL, 0, "<Branch>", NULL,},
950     {"/Apply as Filter/_Selected", NULL, GTK_MENU_FUNC(match_selected_ptree_cb),
951                        MATCH_SELECTED_REPLACE|MATCH_SELECTED_APPLY_NOW, NULL, NULL,},
952     {"/Apply as Filter/_Not Selected", NULL, GTK_MENU_FUNC(match_selected_ptree_cb),
953                        MATCH_SELECTED_NOT|MATCH_SELECTED_APPLY_NOW, NULL, NULL,},
954     {"/Apply as Filter/... _and Selected", NULL, GTK_MENU_FUNC(match_selected_ptree_cb),
955                        MATCH_SELECTED_AND|MATCH_SELECTED_APPLY_NOW, NULL, NULL,},
956     {"/Apply as Filter/... _or Selected", NULL, GTK_MENU_FUNC(match_selected_ptree_cb),
957                        MATCH_SELECTED_OR|MATCH_SELECTED_APPLY_NOW, NULL, NULL,},
958     {"/Apply as Filter/... a_nd not Selected", NULL, GTK_MENU_FUNC(match_selected_ptree_cb),
959                        MATCH_SELECTED_AND_NOT|MATCH_SELECTED_APPLY_NOW, NULL, NULL,},
960     {"/Apply as Filter/... o_r not Selected", NULL, GTK_MENU_FUNC(match_selected_ptree_cb),
961                        MATCH_SELECTED_OR_NOT|MATCH_SELECTED_APPLY_NOW, NULL, NULL,},
962
963     {"/Prepare a Filter", NULL, NULL, 0, "<Branch>", NULL,},
964     {"/Prepare a Filter/_Selected", NULL, GTK_MENU_FUNC(match_selected_ptree_cb),
965                        MATCH_SELECTED_REPLACE, NULL, NULL,},
966     {"/Prepare a Filter/_Not Selected", NULL, GTK_MENU_FUNC(match_selected_ptree_cb),
967                        MATCH_SELECTED_NOT, NULL, NULL,},
968     {"/Prepare a Filter/... _and Selected", NULL, GTK_MENU_FUNC(match_selected_ptree_cb),
969                        MATCH_SELECTED_AND, NULL, NULL,},
970     {"/Prepare a Filter/... _or Selected", NULL, GTK_MENU_FUNC(match_selected_ptree_cb),
971                        MATCH_SELECTED_OR, NULL, NULL,},
972     {"/Prepare a Filter/... a_nd not Selected", NULL, GTK_MENU_FUNC(match_selected_ptree_cb),
973                        MATCH_SELECTED_AND_NOT, NULL, NULL,},
974     {"/Prepare a Filter/... o_r not Selected", NULL, GTK_MENU_FUNC(match_selected_ptree_cb),
975                        MATCH_SELECTED_OR_NOT, NULL, NULL,},
976
977     {"/Colorize with Filter", NULL, NULL, 0, "<Branch>", NULL,},
978     {"/Colorize with Filter/Color 1", NULL, GTK_MENU_FUNC(colorize_selected_ptree_cb), 1, "<StockItem>", WIRESHARK_STOCK_COLOR1,},
979     {"/Colorize with Filter/Color 2", NULL, GTK_MENU_FUNC(colorize_selected_ptree_cb), 2, "<StockItem>", WIRESHARK_STOCK_COLOR2,},
980     {"/Colorize with Filter/Color 3", NULL, GTK_MENU_FUNC(colorize_selected_ptree_cb), 3, "<StockItem>", WIRESHARK_STOCK_COLOR3,},
981     {"/Colorize with Filter/Color 4", NULL, GTK_MENU_FUNC(colorize_selected_ptree_cb), 4, "<StockItem>", WIRESHARK_STOCK_COLOR4,},
982     {"/Colorize with Filter/Color 5", NULL, GTK_MENU_FUNC(colorize_selected_ptree_cb), 5, "<StockItem>", WIRESHARK_STOCK_COLOR5,},
983     {"/Colorize with Filter/Color 6", NULL, GTK_MENU_FUNC(colorize_selected_ptree_cb), 6, "<StockItem>", WIRESHARK_STOCK_COLOR6,},
984     {"/Colorize with Filter/Color 7", NULL, GTK_MENU_FUNC(colorize_selected_ptree_cb), 7, "<StockItem>", WIRESHARK_STOCK_COLOR7,},
985     {"/Colorize with Filter/Color 8", NULL, GTK_MENU_FUNC(colorize_selected_ptree_cb), 8, "<StockItem>", WIRESHARK_STOCK_COLOR8,},
986     {"/Colorize with Filter/Color 9", NULL, GTK_MENU_FUNC(colorize_selected_ptree_cb), 9, "<StockItem>", WIRESHARK_STOCK_COLOR9,},
987     {"/Colorize with Filter/Color 10", NULL, GTK_MENU_FUNC(colorize_selected_ptree_cb), 10, "<StockItem>", WIRESHARK_STOCK_COLOR0,},
988     {"/Colorize with Filter/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
989     {"/Colorize with Filter/New Coloring Rule...", NULL, GTK_MENU_FUNC(colorize_selected_ptree_cb), 0, "<StockItem>", GTK_STOCK_SELECT_COLOR,},
990
991     {"/Follow TCP Stream", NULL, GTK_MENU_FUNC(follow_tcp_stream_cb),
992                        0, NULL, NULL,},
993     {"/Follow UDP Stream", NULL, GTK_MENU_FUNC(follow_udp_stream_cb),
994                        0, NULL, NULL,},
995     {"/Follow SSL Stream", NULL, GTK_MENU_FUNC(follow_ssl_stream_cb),
996                        0, NULL, NULL,},
997
998     {"/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
999
1000     {"/Copy", NULL, NULL, 0, "<Branch>", NULL,},
1001     {"/Copy/Description", NULL, GTK_MENU_FUNC(copy_selected_plist_cb), 0, NULL, NULL,},
1002     {"/Copy/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
1003     {"/Copy/As Filter", NULL, GTK_MENU_FUNC(match_selected_ptree_cb), MATCH_SELECTED_REPLACE|MATCH_SELECTED_COPY_ONLY, NULL, NULL,},
1004     {"/Copy/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
1005     {"/Copy/Bytes (Offset Hex Text)", NULL, GTK_MENU_FUNC(copy_hex_cb), CD_ALLINFO | CD_FLAGS_SELECTEDONLY, NULL, NULL,},
1006     {"/Copy/Bytes (Offset Hex)", NULL, GTK_MENU_FUNC(copy_hex_cb), CD_HEXCOLUMNS | CD_FLAGS_SELECTEDONLY, NULL, NULL,},
1007     {"/Copy/Bytes (Printable Text Only)", NULL, GTK_MENU_FUNC(copy_hex_cb), CD_TEXTONLY | CD_FLAGS_SELECTEDONLY, NULL, NULL,},
1008     {"/Copy/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
1009     {"/Copy/Bytes (Hex Stream)", NULL, GTK_MENU_FUNC(copy_hex_cb), CD_HEX | CD_FLAGS_SELECTEDONLY, NULL, NULL,},
1010     {"/Copy/Bytes (Binary Stream)", NULL, GTK_MENU_FUNC(copy_hex_cb), CD_BINARY | CD_FLAGS_SELECTEDONLY, NULL, NULL,},
1011
1012     {"/Export Selected Packet Bytes...", NULL, GTK_MENU_FUNC(savehex_cb),
1013                        0, NULL, NULL,},
1014
1015     {"/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
1016
1017     {"/Wiki Protocol Page", NULL, GTK_MENU_FUNC(selected_ptree_info_cb),
1018                        0, "<StockItem>", WIRESHARK_STOCK_WIKI,},
1019     {"/Filter Field Reference", NULL, GTK_MENU_FUNC(selected_ptree_ref_cb),
1020                        0, "<StockItem>", WIRESHARK_STOCK_INTERNET,},
1021     {"/Protocol Preferences...", NULL, GTK_MENU_FUNC(properties_cb),
1022                        0, NULL, NULL,},
1023     {"/<separator>", NULL, NULL, 0, "<Separator>", NULL,},
1024     {"/Decode As...", NULL, GTK_MENU_FUNC(decode_as_cb), 0, "<StockItem>", WIRESHARK_STOCK_DECODE_AS,},
1025     {"/Disable Protocol...", NULL, GTK_MENU_FUNC(proto_disable_cb), 0, "<StockItem>", WIRESHARK_STOCK_CHECKBOX,},
1026     {"/_Resolve Name", NULL, GTK_MENU_FUNC(resolve_name_cb), 0, NULL, NULL,},
1027     {"/_Go to Corresponding Packet", NULL, GTK_MENU_FUNC(goto_framenum_cb), 0, NULL, NULL,}
1028 };
1029
1030
1031 static int initialize = TRUE;
1032 static GtkItemFactory *main_menu_factory = NULL;
1033 static GtkItemFactory *packet_list_menu_factory = NULL;
1034 static GtkItemFactory *tree_view_menu_factory = NULL;
1035 static GtkItemFactory *hexdump_menu_factory = NULL;
1036
1037 static GSList *popup_menu_list = NULL;
1038
1039 static GtkAccelGroup *grp;
1040
1041 GtkWidget *
1042 main_menu_new(GtkAccelGroup ** table) {
1043     GtkWidget *menubar;
1044
1045     grp = gtk_accel_group_new();
1046
1047     if (initialize)
1048         menus_init();
1049
1050     menubar = main_menu_factory->widget;
1051
1052     if (table)
1053         *table = grp;
1054
1055     return menubar;
1056 }
1057
1058
1059 void menu_dissector_filter_cb(  GtkWidget *widget _U_,
1060                                 gpointer callback_data,
1061                                 guint callback_action _U_)
1062 {
1063     dissector_filter_t      *filter_entry = callback_data;
1064     GtkWidget                   *filter_te;
1065     const char              *buf;    
1066
1067
1068     filter_te = g_object_get_data(G_OBJECT(popup_menu_object), E_DFILTER_TE_KEY);
1069
1070     /* XXX - this gets the packet_info of the last dissected packet, */
1071     /* which is not necessarily the last selected packet */
1072     /* e.g. "Update list of packets in real time" won't work correct */
1073     buf = filter_entry->build_filter_string(&cfile.edt->pi);
1074
1075         gtk_entry_set_text(GTK_ENTRY(filter_te), buf);
1076
1077         /* Run the display filter so it goes in effect - even if it's the
1078            same as the previous display filter. */
1079         main_filter_packets(&cfile, buf, TRUE);
1080
1081     g_free( (void *) buf);
1082 }
1083
1084 gboolean menu_dissector_filter_spe_cb(frame_data *fd _U_, epan_dissect_t *edt, gpointer callback_data) {
1085     dissector_filter_t *filter_entry = callback_data;
1086
1087     /* XXX - this gets the packet_info of the last dissected packet, */
1088     /* which is not necessarily the last selected packet */
1089     /* e.g. "Update list of packets in real time" won't work correct */
1090     return (edt != NULL) ? filter_entry->is_filter_valid(&edt->pi) : FALSE;
1091 }
1092
1093 void menu_dissector_filter(void) {
1094     GList *list_entry = dissector_filter_list;
1095     dissector_filter_t *filter_entry;
1096
1097     while(list_entry != NULL) {
1098         filter_entry = list_entry->data;
1099
1100         register_stat_menu_item(filter_entry->name, REGISTER_ANALYZE_GROUP_CONVERSATION_FILTER,
1101             menu_dissector_filter_cb,
1102             menu_dissector_filter_spe_cb,
1103             NULL /* selected_tree_row_enabled */,
1104             filter_entry);
1105
1106         list_entry = g_list_next(list_entry);
1107     }
1108 }
1109
1110
1111 static void
1112 menus_init(void) {
1113   if (initialize) {
1114     initialize = FALSE;
1115
1116     /* popup */
1117     packet_list_menu_factory = gtk_item_factory_new(GTK_TYPE_MENU, "<main>", NULL);
1118     popup_menu_object = gtk_menu_new();
1119     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);
1120     g_object_set_data(G_OBJECT(popup_menu_object), PM_PACKET_LIST_KEY,
1121                     packet_list_menu_factory->widget);
1122     popup_menu_list = g_slist_append((GSList *)popup_menu_list, packet_list_menu_factory);
1123
1124     tree_view_menu_factory = gtk_item_factory_new(GTK_TYPE_MENU, "<main>", NULL);
1125     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);
1126     g_object_set_data(G_OBJECT(popup_menu_object), PM_TREE_VIEW_KEY,
1127                     tree_view_menu_factory->widget);
1128     popup_menu_list = g_slist_append((GSList *)popup_menu_list, tree_view_menu_factory);
1129
1130     hexdump_menu_factory = gtk_item_factory_new(GTK_TYPE_MENU, "<main>", NULL);
1131     g_object_set_data(G_OBJECT(popup_menu_object), PM_HEXDUMP_KEY,
1132                     hexdump_menu_factory->widget);
1133     popup_menu_list = g_slist_append((GSList *)popup_menu_list, hexdump_menu_factory);
1134     /* main */
1135     main_menu_factory = gtk_item_factory_new(GTK_TYPE_MENU_BAR, "<main>", grp);
1136     gtk_item_factory_create_items_ac(main_menu_factory, nmenu_items, menu_items, NULL, 2);
1137
1138     menu_dissector_filter();
1139     merge_all_tap_menus(tap_menu_tree_root);
1140
1141     /* Initialize enabled/disabled state of menu items */
1142     set_menus_for_capture_file(NULL);
1143 #if 0
1144     /* Un-#if this when we actually implement Cut/Copy/Paste.
1145        Then make sure you enable them when they can be done. */
1146     set_menu_sensitivity(main_menu_factory, "/Edit/Cut", FALSE);
1147     set_menu_sensitivity(main_menu_factory, "/Edit/Copy", FALSE);
1148     set_menu_sensitivity(main_menu_factory, "/Edit/Paste", FALSE);
1149 #endif
1150
1151     set_menus_for_captured_packets(FALSE);
1152     set_menus_for_selected_packet(&cfile);
1153     set_menus_for_selected_tree_row(&cfile);
1154     set_menus_for_capture_in_progress(FALSE);
1155     set_menus_for_file_set(/* dialog */TRUE, /* previous file */ FALSE, /* next_file */ FALSE);
1156
1157     /* init with an empty recent files list */
1158     clear_menu_recent_capture_file_cmd_cb(NULL, NULL);
1159
1160   }
1161 }
1162
1163
1164 static gint tap_menu_item_add_compare(gconstpointer a, gconstpointer b)
1165 {
1166     return strcmp(
1167         ((const menu_item_t *) a)->name,
1168         ((const menu_item_t *) b)->name);
1169 }
1170
1171
1172 /* add a menuitem below the current node */
1173 static GList * tap_menu_item_add(
1174     char *name,
1175     gint group,
1176     const char *stock_id,
1177     GtkItemFactoryCallback callback,
1178     gboolean (*selected_packet_enabled)(frame_data *, epan_dissect_t *, gpointer callback_data),
1179     gboolean (*selected_tree_row_enabled)(field_info *, gpointer callback_data),
1180     gpointer callback_data,
1181     GList *curnode)
1182 {
1183     menu_item_t *curr;
1184     menu_item_t *child;
1185
1186
1187     child = g_malloc(sizeof (menu_item_t));
1188     child->name             = name;
1189     child->group            = group;
1190     child->stock_id         = stock_id;
1191     child->callback         = callback;
1192     child->selected_packet_enabled = selected_packet_enabled;
1193     child->selected_tree_row_enabled = selected_tree_row_enabled;
1194     child->callback_data    = callback_data;
1195     child->enabled          = FALSE;
1196     child->children         = NULL;
1197
1198     /* insert the new child node into the parent */
1199     curr = curnode->data;
1200     curr->children = g_list_insert_sorted(curr->children, child, tap_menu_item_add_compare);
1201
1202     /* return the new node */
1203     /* XXX: improve this */
1204     return g_list_find(curr->children, child);
1205 }
1206
1207 /*
1208  * Add a new menu item for a tap.
1209  * This must be called after we've created the main menu, so it can't
1210  * be called from the routine that registers taps - we have to introduce
1211  * another per-tap registration routine.
1212  *
1213  * "callback" gets called when the menu item is selected; it should do
1214  * the work of creating the tap window.
1215  *
1216  * "selected_packet_enabled" gets called by "set_menus_for_selected_packet()";
1217  * it's passed a Boolean that's TRUE if a packet is selected and FALSE
1218  * otherwise, and should return TRUE if the tap will work now (which
1219  * might depend on whether a packet is selected and, if one is, on the
1220  * packet) and FALSE if not.
1221  *
1222  * "selected_tree_row_enabled" gets called by
1223  * "set_menus_for_selected_tree_row()"; it's passed a Boolean that's TRUE if
1224  * a protocol tree row is selected and FALSE otherwise, and should return
1225  * TRUE if the tap will work now (which might depend on whether a tree row
1226  * is selected and, if one is, on the tree row) and FALSE if not.
1227  */
1228 void
1229 register_stat_menu_item_stock(
1230     const char *name,
1231     register_stat_group_t group,
1232     const char *stock_id,
1233     GtkItemFactoryCallback callback,
1234     gboolean (*selected_packet_enabled)(frame_data *, epan_dissect_t *, gpointer callback_data),
1235     gboolean (*selected_tree_row_enabled)(field_info *, gpointer callback_data),
1236     gpointer callback_data)
1237 {
1238     /*static const char toolspath[] = "/Statistics/";*/
1239     const char *toolspath;
1240     const char *p;
1241     char *menupath;
1242     size_t menupathlen;
1243     menu_item_t *child;
1244     GList *curnode;
1245     GList *childnode;
1246
1247     /*
1248      * The menu path must be relative.
1249      */
1250     g_assert(*name != '/');
1251
1252     switch(group) {
1253     case(REGISTER_STAT_GROUP_GENERIC): toolspath = "/Statistics/"; break;
1254     case(REGISTER_STAT_GROUP_CONVERSATION_LIST): toolspath = "/Statistics/_Conversation List/"; break;
1255     case(REGISTER_STAT_GROUP_ENDPOINT_LIST): toolspath = "/Statistics/_Endpoint List/"; break;
1256     case(REGISTER_STAT_GROUP_RESPONSE_TIME): toolspath = "/Statistics/Service _Response Time/"; break;
1257     case(REGISTER_STAT_GROUP_TELEPHONY): toolspath = "/Statistics/"; break;
1258     case(REGISTER_STAT_GROUP_UNSORTED): toolspath = "/Statistics/"; break;
1259     case(REGISTER_ANALYZE_GROUP_UNSORTED): toolspath = "/Analyze/"; break;
1260     case(REGISTER_ANALYZE_GROUP_CONVERSATION_FILTER): toolspath = "/Analyze/Conversation Filter/"; break;
1261     case(REGISTER_TOOLS_GROUP_UNSORTED): toolspath = "/Tools/"; break;
1262     default:
1263         g_assert(!"no such menu group");
1264         toolspath = NULL;
1265     }
1266
1267     /* add the (empty) root node, if not already done */
1268     if(tap_menu_tree_root == NULL) {
1269         child = g_malloc0(sizeof (menu_item_t));
1270         tap_menu_tree_root = g_list_append(NULL, child);
1271     }
1272
1273     /*
1274      * Create any submenus required.
1275      */
1276     curnode = tap_menu_tree_root;
1277     p = name;
1278     while ((p = strchr(p, '/')) != NULL) {
1279         /*
1280          * OK, everything between "name" and "p" is
1281          * a menu relative subtree into which the menu item
1282          * will be placed.
1283          *
1284          * Construct the absolute path name of that subtree.
1285          */
1286         menupathlen = strlen(toolspath) + 1 + (p - name);
1287         menupath = g_malloc(menupathlen);
1288         g_strlcpy(menupath, toolspath, menupathlen);
1289         g_strlcat(menupath, name, menupathlen);
1290
1291         /*
1292          * Does there exist an entry with that path at this
1293          * level of the Analyze menu tree?
1294          */
1295         child = curnode->data;
1296         for (childnode = child->children; childnode != NULL; childnode = childnode->next) {
1297             child = childnode->data;
1298             if (strcmp(child->name, menupath) == 0)
1299                 break;
1300         }
1301         if (childnode == NULL) {
1302             /*
1303              * No.  Create such an item as a subtree, and
1304              * add it to the Tools menu tree.
1305              */
1306             childnode = tap_menu_item_add(
1307                 menupath, group, "", NULL, NULL ,NULL, NULL, curnode);
1308         } else {
1309             /*
1310              * Yes.  We don't need this "menupath" any longer.
1311              */
1312             g_free(menupath);
1313         }
1314         curnode = childnode;
1315
1316         /*
1317          * Skip over the '/' we found.
1318          */
1319         p++;
1320     }
1321
1322     /*
1323      * Construct the main menu path for the menu item.
1324      */
1325     menupathlen = strlen(toolspath) + 1 + strlen(name);
1326     menupath = g_malloc(menupathlen);
1327     g_strlcpy(menupath, toolspath, menupathlen);
1328     g_strlcat(menupath, name, menupathlen);
1329
1330     /*
1331      * Construct an item factory entry for the item, and add it to
1332      * the main menu.
1333      */
1334     tap_menu_item_add(
1335         menupath, group, stock_id, callback,
1336         selected_packet_enabled, selected_tree_row_enabled,
1337         callback_data, curnode);
1338 }
1339
1340
1341 void
1342 register_stat_menu_item(
1343     const char *name,
1344     register_stat_group_t group,
1345     GtkItemFactoryCallback callback,
1346     gboolean (*selected_packet_enabled)(frame_data *, epan_dissect_t *, gpointer callback_data),
1347     gboolean (*selected_tree_row_enabled)(field_info *, gpointer callback_data),
1348     gpointer callback_data)
1349 {
1350     register_stat_menu_item_stock(
1351         name,
1352         group,
1353         NULL,
1354         callback,
1355         selected_packet_enabled,
1356         selected_tree_row_enabled,
1357         callback_data);
1358 }
1359
1360 static guint merge_tap_menus_layered(GList *node, gint group) {
1361     GtkItemFactoryEntry *entry;
1362     GList       *child;
1363     guint       added = 0;
1364     menu_item_t *node_data = node->data;
1365
1366     /*
1367      * Is this a leaf node or an interior node?
1368      */
1369     if (node_data->children == NULL) {
1370         /*
1371          * It's a leaf node.
1372          */
1373
1374         /*
1375          * The root node doesn't correspond to a menu tree item; it
1376          * has a null name pointer.
1377          */
1378         if (node_data->name != NULL && group == node_data->group) {
1379             entry = g_malloc0(sizeof (GtkItemFactoryEntry));
1380             entry->path = node_data->name;
1381             entry->callback = node_data->callback;
1382             switch(group) {
1383             case(REGISTER_STAT_GROUP_UNSORTED):
1384                 break;
1385             case(REGISTER_STAT_GROUP_GENERIC):
1386                 break;
1387             case(REGISTER_STAT_GROUP_CONVERSATION_LIST):
1388                 entry->item_type = "<StockItem>";
1389                 entry->extra_data = WIRESHARK_STOCK_CONVERSATIONS;
1390                 break;
1391             case(REGISTER_STAT_GROUP_ENDPOINT_LIST):
1392                 entry->item_type = "<StockItem>";
1393                 entry->extra_data = WIRESHARK_STOCK_ENDPOINTS;
1394                 break;
1395             case(REGISTER_STAT_GROUP_RESPONSE_TIME):
1396                 entry->item_type = "<StockItem>";
1397                 entry->extra_data = WIRESHARK_STOCK_TIME;
1398                 break;
1399             case(REGISTER_STAT_GROUP_TELEPHONY):
1400                 entry->item_type = "<StockItem>";
1401                 entry->extra_data = WIRESHARK_STOCK_TELEPHONY;
1402                 break;
1403             case(REGISTER_ANALYZE_GROUP_UNSORTED):
1404                 break;
1405             case(REGISTER_ANALYZE_GROUP_CONVERSATION_FILTER):
1406                 break;
1407             case(REGISTER_TOOLS_GROUP_UNSORTED):
1408                 break;
1409             default:
1410                 g_assert_not_reached();
1411             }
1412             if(node_data->stock_id!= NULL) {
1413                 entry->item_type = "<StockItem>";
1414                 entry->extra_data = node_data->stock_id;
1415             }
1416             gtk_item_factory_create_item(main_menu_factory, entry, node_data->callback_data, /* callback_type */ 2);
1417             set_menu_sensitivity(main_menu_factory, node_data->name, FALSE); /* no capture file yet */
1418             added++;
1419             g_free(entry);
1420         }
1421     } else {
1422         /*
1423          * It's an interior node; call
1424          * "merge_tap_menus_layered()" on all its children
1425          */
1426
1427         /*
1428          * The root node doesn't correspond to a menu tree item; it
1429          * has a null name pointer.
1430          */
1431         if (node_data->name != NULL && group == node_data->group) {
1432             entry = g_malloc0(sizeof (GtkItemFactoryEntry));
1433             entry->path = node_data->name;
1434             entry->item_type = "<Branch>";
1435             gtk_item_factory_create_item(main_menu_factory, entry,
1436                 NULL, 2);
1437             set_menu_sensitivity(main_menu_factory, node_data->name,
1438                 FALSE);    /* no children yet */
1439             added++;
1440             g_free(entry);
1441         }
1442
1443         for (child = node_data->children; child != NULL; child =
1444             child->next) {
1445             added += merge_tap_menus_layered(child, group);
1446         }
1447     }
1448
1449     return added;
1450 }
1451
1452
1453 void merge_all_tap_menus(GList *node) {
1454     GtkItemFactoryEntry *sep_entry;
1455
1456     sep_entry = g_malloc0(sizeof (GtkItemFactoryEntry));
1457     sep_entry->item_type = "<Separator>";
1458     sep_entry->path = "/Statistics/";
1459
1460     /*
1461      * merge only the menu items of the specific group,
1462      * and then append a seperator
1463      */
1464     if (merge_tap_menus_layered(node, REGISTER_STAT_GROUP_GENERIC)) {
1465         gtk_item_factory_create_item(main_menu_factory, sep_entry, NULL, 2);
1466     }
1467     if (merge_tap_menus_layered(node, REGISTER_STAT_GROUP_CONVERSATION_LIST)) {
1468         /*gtk_item_factory_create_item(main_menu_factory, sep_entry, NULL, 2);*/
1469     }
1470     if (merge_tap_menus_layered(node, REGISTER_STAT_GROUP_ENDPOINT_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_RESPONSE_TIME)) {
1474         gtk_item_factory_create_item(main_menu_factory, sep_entry, NULL, 2);
1475     }
1476     if (merge_tap_menus_layered(node, REGISTER_STAT_GROUP_TELEPHONY)) {
1477         gtk_item_factory_create_item(main_menu_factory, sep_entry, NULL, 2);
1478     }
1479     if (merge_tap_menus_layered(node, REGISTER_STAT_GROUP_UNSORTED)) {
1480         /*gtk_item_factory_create_item(main_menu_factory, sep_entry, NULL, 2);*/
1481     }
1482     if (merge_tap_menus_layered(node, REGISTER_ANALYZE_GROUP_UNSORTED)) {
1483         sep_entry->path = "/Analyze/";
1484         /*gtk_item_factory_create_item(main_menu_factory, sep_entry, NULL, 2);*/
1485     }
1486     if (merge_tap_menus_layered(node, REGISTER_ANALYZE_GROUP_CONVERSATION_FILTER)) {
1487         sep_entry->path = "/Analyze/Conversation Filter/";
1488         /*gtk_item_factory_create_item(main_menu_factory, sep_entry, NULL, 2);*/
1489     }
1490     if (merge_tap_menus_layered(node, REGISTER_TOOLS_GROUP_UNSORTED)) {
1491         /*gtk_item_factory_create_item(main_menu_factory, sep_entry, NULL, 2);*/
1492     }
1493 }
1494
1495
1496
1497 /*
1498  * Enable/disable menu sensitivity.
1499  */
1500 static void
1501 set_menu_sensitivity(GtkItemFactory *ifactory, const gchar *path, gint val)
1502 {
1503   GSList *menu_list;
1504   GtkWidget *menu_item;
1505   gchar *dup;
1506   gchar *dest;
1507
1508
1509   /* the underscore character regularly confuses things, as it will prevent finding
1510    * the menu_item, so it has to be removed first */
1511   dup = g_strdup(path);
1512   dest = dup;
1513   while(*path) {
1514       if (*path != '_') {
1515         *dest = *path;
1516         dest++;
1517       }
1518       path++;
1519   }
1520   *dest = '\0';
1521
1522   if (ifactory == NULL) {
1523     /*
1524      * Do it for all pop-up menus.
1525      */
1526     for (menu_list = popup_menu_list; menu_list != NULL;
1527          menu_list = g_slist_next(menu_list))
1528       set_menu_sensitivity(menu_list->data, dup, val);
1529   } else {
1530     /*
1531      * Do it for that particular menu.
1532      */
1533     if ((menu_item = gtk_item_factory_get_widget(ifactory, dup)) != NULL) {
1534       if (GTK_IS_MENU(menu_item)) {
1535         /*
1536          * "dup" refers to a submenu; "gtk_item_factory_get_widget()"
1537          * gets the menu, not the item that, when selected, pops up
1538          * the submenu.
1539          *
1540          * We have to change the latter item's sensitivity, so that
1541          * it shows up normally if sensitive and grayed-out if
1542          * insensitive.
1543          */
1544         menu_item = gtk_menu_get_attach_widget(GTK_MENU(menu_item));
1545       }
1546       gtk_widget_set_sensitive(menu_item, val);
1547     } else{
1548       /* be sure this menu item *is* existing */
1549       g_assert_not_reached();
1550     }
1551   }
1552
1553   g_free(dup);
1554 }
1555
1556 static void
1557 set_menu_object_data_meat(GtkItemFactory *ifactory, const gchar *path, const gchar *key, gpointer data)
1558 {
1559         GtkWidget *menu = NULL;
1560
1561         if ((menu = gtk_item_factory_get_widget(ifactory, path)) != NULL)
1562                 g_object_set_data(G_OBJECT(menu), key, data);
1563 }
1564
1565 void
1566 set_menu_object_data (const gchar *path, const gchar *key, gpointer data) {
1567   GSList *menu_list = popup_menu_list;
1568   gchar *shortpath = strrchr(path, '/');
1569
1570   set_menu_object_data_meat(main_menu_factory, path, key, data);
1571   while (menu_list != NULL) {
1572     set_menu_object_data_meat(menu_list->data, shortpath, key, data);
1573     set_menu_object_data_meat(menu_list->data, path, key, data);
1574     menu_list = g_slist_next(menu_list);
1575   }
1576 }
1577
1578
1579 /* Recently used capture files submenu:
1580  * Submenu containing the recently used capture files.
1581  * The capture filenames are always kept with the absolute path, to be independant
1582  * of the current path.
1583  * They are only stored inside the labels of the submenu (no separate list). */
1584
1585 #define MENU_RECENT_FILES_PATH "/File/Open Recent"
1586 #define MENU_RECENT_FILES_KEY "Recent File Name"
1587
1588
1589
1590 static void
1591 update_menu_recent_capture_file1(GtkWidget *widget, gpointer cnt) {
1592     gchar *widget_cf_name;
1593
1594     widget_cf_name = g_object_get_data(G_OBJECT(widget), MENU_RECENT_FILES_KEY);
1595
1596     /* if this menu item is a file, count it */
1597     if (widget_cf_name) {
1598         (*(guint *)cnt)++;
1599         main_welcome_add_recent_capture_files(widget_cf_name);
1600     }
1601 }
1602
1603
1604
1605 /* update the menu */
1606 static void
1607 update_menu_recent_capture_file(GtkWidget *submenu_recent_files) {
1608     guint cnt = 0;
1609
1610
1611     main_welcome_reset_recent_capture_files();
1612
1613     gtk_container_foreach(GTK_CONTAINER(submenu_recent_files),
1614                 update_menu_recent_capture_file1, &cnt);
1615
1616     /* make parent menu item sensitive only, if we have any valid files in the list */
1617     set_menu_sensitivity(main_menu_factory, MENU_RECENT_FILES_PATH, cnt);
1618 }
1619
1620
1621
1622 /* remove the capture filename from the "Recent Files" menu */
1623 static void
1624 remove_menu_recent_capture_filename(gchar *cf_name) {
1625     GtkWidget *submenu_recent_files;
1626     GList* child_list;
1627     GList* child_list_item;
1628         GtkWidget *menu_item_child;
1629         gchar     *menu_item_cf_name;
1630     
1631
1632     /* get the submenu container item */
1633     submenu_recent_files = gtk_item_factory_get_widget(main_menu_factory, MENU_RECENT_FILES_PATH);
1634
1635     /* find the corresponding menu item to be removed */
1636     child_list = gtk_container_get_children(GTK_CONTAINER(submenu_recent_files));
1637     child_list_item = child_list;
1638     while(child_list_item) {
1639             menu_item_child = (GTK_BIN(child_list_item->data))->child;
1640             gtk_label_get(GTK_LABEL(menu_item_child), &menu_item_cf_name);
1641         if(strcmp(menu_item_cf_name, cf_name) == 0) {
1642             /* XXX: is this all we need to do, to free the menu item and its label?
1643                The reference count of widget will go to 0, so it'll be freed;
1644                will that free the label? */
1645             gtk_container_remove(GTK_CONTAINER(submenu_recent_files), child_list_item->data);
1646         }
1647         child_list_item = g_list_next(child_list_item);
1648     }
1649     g_list_free(child_list);
1650
1651     update_menu_recent_capture_file(submenu_recent_files);
1652 }
1653
1654
1655 /* remove the capture filename from the "Recent Files" menu */
1656 static void
1657 remove_menu_recent_capture_file(GtkWidget *widget, gpointer unused _U_) {
1658     GtkWidget *submenu_recent_files;
1659     gchar *widget_cf_name;
1660
1661
1662     widget_cf_name = g_object_get_data(G_OBJECT(widget), MENU_RECENT_FILES_KEY);
1663     g_free(widget_cf_name);
1664
1665     /* get the submenu container item */
1666     submenu_recent_files = gtk_item_factory_get_widget(main_menu_factory, MENU_RECENT_FILES_PATH);
1667
1668     /* XXX: is this all we need to do, to free the menu item and its label?
1669        The reference count of widget will go to 0, so it'll be freed;
1670        will that free the label? */
1671     gtk_container_remove(GTK_CONTAINER(submenu_recent_files), widget);
1672 }
1673
1674
1675 /* callback, if the user pushed the <Clear> menu item */
1676 static void
1677 clear_menu_recent_capture_file_cmd_cb(GtkWidget *w _U_, gpointer unused _U_) {
1678     GtkWidget *submenu_recent_files;
1679
1680
1681     submenu_recent_files = gtk_item_factory_get_widget(main_menu_factory, MENU_RECENT_FILES_PATH);
1682
1683     gtk_container_foreach(GTK_CONTAINER(submenu_recent_files),
1684                 remove_menu_recent_capture_file, NULL);
1685
1686     update_menu_recent_capture_file(submenu_recent_files);
1687 }
1688
1689
1690 /* Open a file by it's name
1691    (Beware: will not ask to close existing capture file!) */
1692 void
1693 menu_open_filename(gchar *cf_name)
1694 {
1695         GtkWidget *submenu_recent_files;
1696         int       err;
1697
1698         submenu_recent_files = gtk_item_factory_get_widget(main_menu_factory, MENU_RECENT_FILES_PATH);
1699
1700         /* open and read the capture file (this will close an existing file) */
1701         if (cf_open(&cfile, cf_name, FALSE, &err) == CF_OK) {
1702                 cf_read(&cfile);
1703         } else {
1704                 /* the capture file isn't existing any longer, remove menu item */
1705                 /* XXX: ask user to remove item, it's maybe only a temporary problem */
1706                 remove_menu_recent_capture_filename(cf_name);
1707         }
1708
1709         update_menu_recent_capture_file(submenu_recent_files);
1710 }
1711
1712
1713 /* callback, if the user pushed a recent file submenu item */
1714 void
1715 menu_open_recent_file_cmd(GtkWidget *w)
1716 {
1717         GtkWidget *submenu_recent_files;
1718         GtkWidget *menu_item_child;
1719         gchar     *cf_name;
1720         int       err;
1721
1722         submenu_recent_files = gtk_item_factory_get_widget(main_menu_factory, MENU_RECENT_FILES_PATH);
1723
1724         /* get capture filename from the menu item label */
1725         menu_item_child = (GTK_BIN(w))->child;
1726         gtk_label_get(GTK_LABEL(menu_item_child), &cf_name);
1727
1728         /* open and read the capture file (this will close an existing file) */
1729         if (cf_open(&cfile, cf_name, FALSE, &err) == CF_OK) {
1730                 cf_read(&cfile);
1731         } else {
1732                 /* the capture file isn't existing any longer, remove menu item */
1733                 /* XXX: ask user to remove item, it's maybe only a temporary problem */
1734                 remove_menu_recent_capture_file(w, NULL);
1735         }
1736
1737         update_menu_recent_capture_file(submenu_recent_files);
1738 }
1739
1740 static void menu_open_recent_file_answered_cb(gpointer dialog _U_, gint btn, gpointer data)
1741 {
1742     switch(btn) {
1743     case(ESD_BTN_YES):
1744         /* save file first */
1745         file_save_as_cmd(after_save_open_recent_file, data);
1746         break;
1747     case(ESD_BTN_NO):
1748         cf_close(&cfile);
1749         menu_open_recent_file_cmd(data);
1750         break;
1751     case(ESD_BTN_CANCEL):
1752         break;
1753     default:
1754         g_assert_not_reached();
1755     }
1756 }
1757
1758 static void
1759 menu_open_recent_file_cmd_cb(GtkWidget *widget, gpointer data _U_) {
1760   gpointer  dialog;
1761
1762
1763   if((cfile.state != FILE_CLOSED) && !cfile.user_saved && prefs.gui_ask_unsaved) {
1764     /* user didn't saved his current file, ask him */
1765     dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_YES_NO_CANCEL,
1766                 "%sSave capture file before opening a new one?%s\n\n"
1767                 "If you open a new capture file without saving, your current capture data will be discarded.",
1768                 simple_dialog_primary_start(), simple_dialog_primary_end());
1769     simple_dialog_set_cb(dialog, menu_open_recent_file_answered_cb, widget);
1770   } else {
1771     /* unchanged file */
1772     menu_open_recent_file_cmd(widget);
1773   }
1774 }
1775
1776 /* add the capture filename (with an absolute path) to the "Recent Files" menu */
1777 static void
1778 add_menu_recent_capture_file_absolute(gchar *cf_name) {
1779         GtkWidget *submenu_recent_files;
1780         GList *menu_item_list;
1781         GList *li;
1782         gchar *widget_cf_name;
1783         gchar *normalized_cf_name;
1784         GtkWidget *menu_item;
1785         guint cnt;
1786
1787
1788
1789         normalized_cf_name = g_strdup(cf_name);
1790 #ifdef _WIN32
1791         /* replace all slashes by backslashes */
1792         g_strdelimit(normalized_cf_name, "/", '\\');
1793 #endif
1794
1795         /* get the submenu container item */
1796         submenu_recent_files = gtk_item_factory_get_widget(main_menu_factory, MENU_RECENT_FILES_PATH);
1797
1798         /* convert container to a GList */
1799         menu_item_list = gtk_container_get_children(GTK_CONTAINER(submenu_recent_files));
1800
1801         /* iterate through list items of menu_item_list,
1802          * removing special items, a maybe duplicate entry and every item above count_max */
1803         cnt = 1;
1804         for (li = g_list_first(menu_item_list); li; li = li->next, cnt++) {
1805                 /* get capture filename */
1806                 menu_item = GTK_WIDGET(li->data);
1807                 widget_cf_name = g_object_get_data(G_OBJECT(menu_item), MENU_RECENT_FILES_KEY);
1808
1809                 /* if this element string is one of our special items (seperator, ...) or
1810                  * already in the list or
1811                  * this element is above maximum count (too old), remove it */
1812                 if (!widget_cf_name ||
1813 #ifdef _WIN32
1814                     /* do a case insensitive compare on win32 */
1815                     g_ascii_strncasecmp(widget_cf_name, normalized_cf_name, 1000) == 0 ||
1816 #else   /* _WIN32 */
1817                     /* do a case sensitive compare on unix */
1818                     strncmp(widget_cf_name, normalized_cf_name, 1000) == 0 ||
1819 #endif
1820                     cnt >= prefs.gui_recent_files_count_max) {
1821                         remove_menu_recent_capture_file(li->data, NULL);
1822                         cnt--;
1823                 }
1824         }
1825
1826         g_list_free(menu_item_list);
1827
1828         /* add new item at latest position */
1829         menu_item = gtk_menu_item_new_with_label(normalized_cf_name);
1830         g_object_set_data(G_OBJECT(menu_item), MENU_RECENT_FILES_KEY, normalized_cf_name);
1831         gtk_menu_shell_prepend (GTK_MENU_SHELL(submenu_recent_files), menu_item);
1832         g_signal_connect_swapped(GTK_OBJECT(menu_item), "activate",
1833                 G_CALLBACK(menu_open_recent_file_cmd_cb), (GtkObject *) menu_item);
1834         gtk_widget_show (menu_item);
1835
1836         /* add seperator at last position */
1837         menu_item = gtk_menu_item_new();
1838         gtk_menu_append (GTK_MENU(submenu_recent_files), menu_item);
1839         gtk_widget_show (menu_item);
1840
1841         /* add new "clear list" item at last position */
1842         menu_item = gtk_image_menu_item_new_from_stock(GTK_STOCK_CLEAR, NULL);
1843         gtk_menu_append (GTK_MENU(submenu_recent_files), menu_item);
1844         g_signal_connect_swapped(GTK_OBJECT(menu_item), "activate",
1845                 G_CALLBACK(clear_menu_recent_capture_file_cmd_cb), (GtkObject *) menu_item);
1846         gtk_widget_show (menu_item);
1847
1848         update_menu_recent_capture_file(submenu_recent_files);
1849 }
1850
1851
1852 /* add the capture filename to the "Recent Files" menu */
1853 /* (will change nothing, if this filename is already in the menu) */
1854 void
1855 add_menu_recent_capture_file(gchar *cf_name) {
1856         gchar *curr;
1857         gchar *absolute;
1858
1859
1860         /* if this filename is an absolute path, we can use it directly */
1861         if (g_path_is_absolute(cf_name)) {
1862                 add_menu_recent_capture_file_absolute(cf_name);
1863                 return;
1864         }
1865
1866         /* this filename is not an absolute path, prepend the current dir */
1867         curr = g_get_current_dir();
1868         absolute = g_strdup_printf("%s%s%s", curr, G_DIR_SEPARATOR_S, cf_name);
1869         add_menu_recent_capture_file_absolute(absolute);
1870         g_free(curr);
1871         g_free(absolute);
1872 }
1873
1874
1875 /* write all capture filenames of the menu to the user's recent file */
1876 void
1877 menu_recent_file_write_all(FILE *rf) {
1878     GtkWidget   *submenu_recent_files;
1879     GList       *children;
1880     GList       *child;
1881     gchar       *cf_name;
1882
1883
1884     submenu_recent_files = gtk_item_factory_get_widget(main_menu_factory, MENU_RECENT_FILES_PATH);
1885
1886     /* we have to iterate backwards through the children's list,
1887      * so we get the latest item last in the file.
1888      * (don't use gtk_container_foreach() here, it will return the wrong iteration order) */
1889     children = gtk_container_get_children(GTK_CONTAINER(submenu_recent_files));
1890     child = g_list_last(children);
1891     while(child != NULL) {
1892         /* get capture filename from the menu item label */
1893         cf_name = g_object_get_data(G_OBJECT(child->data), MENU_RECENT_FILES_KEY);
1894         if (cf_name) {
1895             if(u3_active())
1896                 fprintf (rf, RECENT_KEY_CAPTURE_FILE ": %s\n", u3_contract_device_path(cf_name));
1897             else
1898                 fprintf (rf, RECENT_KEY_CAPTURE_FILE ": %s\n", cf_name);
1899         }
1900
1901         child = g_list_previous(child);
1902     }
1903
1904     g_list_free(children);
1905 }
1906
1907
1908 static void
1909 show_hide_cb(GtkWidget *w, gpointer data _U_, gint action)
1910 {
1911
1912     /* save current setting in recent */
1913     switch(action) {
1914         case(SHOW_HIDE_MAIN_TOOLBAR):
1915         recent.main_toolbar_show = GTK_CHECK_MENU_ITEM(w)->active;
1916         break;
1917         case(SHOW_HIDE_FILTER_TOOLBAR):
1918         recent.filter_toolbar_show = GTK_CHECK_MENU_ITEM(w)->active;
1919         break;
1920 #ifdef HAVE_AIRPCAP
1921         case(SHOW_HIDE_AIRPCAP_TOOLBAR):
1922         recent.airpcap_toolbar_show = GTK_CHECK_MENU_ITEM(w)->active;
1923         break;
1924 #endif
1925         case(SHOW_HIDE_STATUSBAR):
1926         recent.statusbar_show = GTK_CHECK_MENU_ITEM(w)->active;
1927         break;
1928         case(SHOW_HIDE_PACKET_LIST):
1929         recent.packet_list_show = GTK_CHECK_MENU_ITEM(w)->active;
1930         break;
1931         case(SHOW_HIDE_TREE_VIEW):
1932         recent.tree_view_show = GTK_CHECK_MENU_ITEM(w)->active;
1933         break;
1934         case(SHOW_HIDE_BYTE_VIEW):
1935         recent.byte_view_show = GTK_CHECK_MENU_ITEM(w)->active;
1936         break;
1937         default:
1938             g_assert_not_reached();
1939     }
1940
1941     main_widgets_show_or_hide();
1942 }
1943
1944
1945 static void
1946 timestamp_format_cb(GtkWidget *w _U_, gpointer d _U_, gint action)
1947 {
1948     if (recent.gui_time_format != action) {
1949         timestamp_set_type(action);
1950         recent.gui_time_format = action;
1951         cf_change_time_formats(&cfile);
1952     }
1953 }
1954
1955
1956 static void
1957 timestamp_precision_cb(GtkWidget *w _U_, gpointer d _U_, gint action)
1958 {
1959     if (recent.gui_time_precision != action) {
1960         /* the actual precision will be set in cf_change_time_formats() below */
1961         if (action == TS_PREC_AUTO) {
1962             timestamp_set_precision(TS_PREC_AUTO_SEC);
1963         } else {
1964             timestamp_set_precision(action);
1965         }
1966         recent.gui_time_precision  = action;
1967         cf_change_time_formats(&cfile);
1968     }
1969 }
1970
1971
1972 void
1973 menu_name_resolution_changed(void)
1974 {
1975     GtkWidget *menu = NULL;
1976
1977     menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Name Resolution/Enable for MAC Layer");
1978     gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), g_resolv_flags & RESOLV_MAC);
1979
1980     menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Name Resolution/Enable for Network Layer");
1981     gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), g_resolv_flags & RESOLV_NETWORK);
1982
1983     menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Name Resolution/Enable for Transport Layer");
1984     gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), g_resolv_flags & RESOLV_TRANSPORT);
1985 }
1986
1987 static void
1988 name_resolution_cb(GtkWidget *w, gpointer d _U_, gint action)
1989 {
1990     if (GTK_CHECK_MENU_ITEM(w)->active) {
1991         g_resolv_flags |= action;
1992     } else {
1993         g_resolv_flags &= ~action;
1994     }
1995 }
1996
1997 #ifdef HAVE_LIBPCAP
1998 void
1999 menu_auto_scroll_live_changed(gboolean auto_scroll_live_in) {
2000     GtkWidget *menu;
2001
2002
2003     /* tell menu about it */
2004     menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Auto Scroll in Live Capture");
2005     if( ((gboolean) GTK_CHECK_MENU_ITEM(menu)->active) != auto_scroll_live_in) {
2006         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), auto_scroll_live_in);
2007     }
2008
2009     /* tell toolbar about it */
2010     toolbar_auto_scroll_live_changed(auto_scroll_live_in);
2011
2012     /* change auto scroll */
2013     if(auto_scroll_live_in != auto_scroll_live) {
2014         auto_scroll_live  = auto_scroll_live_in;
2015     }
2016 }
2017
2018 static void
2019 auto_scroll_live_cb(GtkWidget *w _U_, gpointer d _U_)
2020 {
2021     menu_auto_scroll_live_changed(GTK_CHECK_MENU_ITEM(w)->active);
2022 }
2023 #endif
2024
2025
2026 void
2027 menu_colorize_changed(gboolean packet_list_colorize) {
2028     GtkWidget *menu;
2029
2030
2031     /* tell menu about it */
2032     menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Colorize Packet List");
2033     if( ((gboolean) GTK_CHECK_MENU_ITEM(menu)->active) != packet_list_colorize) {
2034         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), packet_list_colorize);
2035     }
2036
2037     /* tell toolbar about it */
2038     toolbar_colorize_changed(packet_list_colorize);
2039
2040     /* change colorization */
2041     if(packet_list_colorize != recent.packet_list_colorize) {
2042         recent.packet_list_colorize = packet_list_colorize;
2043         color_filters_enable(packet_list_colorize);
2044         cf_colorize_packets(&cfile);
2045     }
2046 }
2047
2048 static void
2049 colorize_cb(GtkWidget *w, gpointer d _U_)
2050 {
2051     menu_colorize_changed(GTK_CHECK_MENU_ITEM(w)->active);
2052 }
2053
2054
2055 /* the recent file read has finished, update the menu corresponding */
2056 void
2057 menu_recent_read_finished(void) {
2058     GtkWidget *menu = NULL;
2059
2060     menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Main Toolbar");
2061     gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), recent.main_toolbar_show);
2062
2063     menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Filter Toolbar");
2064     gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), recent.filter_toolbar_show);
2065
2066 #ifdef HAVE_AIRPCAP
2067     menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Wireless Toolbar");
2068     gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), recent.airpcap_toolbar_show);
2069 #endif
2070
2071     menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Statusbar");
2072     gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), recent.statusbar_show);
2073
2074     menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Packet List");
2075     gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), recent.packet_list_show);
2076
2077     menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Packet Details");
2078     gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), recent.tree_view_show);
2079
2080     menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Packet Bytes");
2081     gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), recent.byte_view_show);
2082
2083     menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Colorize Packet List");
2084     gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), recent.packet_list_colorize);
2085
2086     menu_name_resolution_changed();
2087
2088 #ifdef HAVE_LIBPCAP
2089     menu = gtk_item_factory_get_widget(main_menu_factory, "/View/Auto Scroll in Live Capture");
2090     gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), auto_scroll_live);
2091 #endif
2092
2093     main_widgets_rearrange();
2094
2095     /* don't change the time format, if we had a command line value */
2096     if (timestamp_get_type() != TS_NOT_SET) {
2097         recent.gui_time_format = timestamp_get_type();
2098     }
2099
2100     switch(recent.gui_time_format) {
2101     case(TS_ABSOLUTE_WITH_DATE):
2102         menu = gtk_item_factory_get_widget(main_menu_factory,
2103             "/View/Time Display Format/Date and Time of Day:   1970-01-01 01:02:03.123456");
2104         /* set_active will not trigger the callback when activating an active item! */
2105         recent.gui_time_format = -1;
2106         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), FALSE);
2107         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), TRUE);
2108         break;
2109     case(TS_ABSOLUTE):
2110         menu = gtk_item_factory_get_widget(main_menu_factory,
2111             "/View/Time Display Format/Time of Day:   01:02:03.123456");
2112         /* set_active will not trigger the callback when activating an active item! */
2113         recent.gui_time_format = -1;
2114         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), TRUE);
2115         break;
2116     case(TS_RELATIVE):
2117         menu = gtk_item_factory_get_widget(main_menu_factory,
2118             "/View/Time Display Format/Seconds Since Beginning of Capture:   123.123456");
2119         recent.gui_time_format = -1;
2120         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), TRUE);
2121         break;
2122     case(TS_DELTA):
2123         menu = gtk_item_factory_get_widget(main_menu_factory,
2124             "/View/Time Display Format/Seconds Since Previous Captured Packet:   1.123456");
2125         recent.gui_time_format = -1;
2126         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), TRUE);
2127         break;
2128     case(TS_DELTA_DIS):
2129         menu = gtk_item_factory_get_widget(main_menu_factory,
2130             "/View/Time Display Format/Seconds Since Previous Displayed Packet:   1.123456");
2131         recent.gui_time_format = -1;
2132         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), TRUE);
2133         break;
2134     case(TS_EPOCH):
2135         menu = gtk_item_factory_get_widget(main_menu_factory,
2136             "/View/Time Display Format/Seconds Since Epoch (1970-01-01):   1234567890.123456");
2137         recent.gui_time_format = -1;
2138         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), TRUE);
2139         break;
2140     default:
2141         g_assert_not_reached();
2142     }
2143
2144     switch(recent.gui_time_precision) {
2145     case(TS_PREC_AUTO):
2146         menu = gtk_item_factory_get_widget(main_menu_factory,
2147             "/View/Time Display Format/Automatic (File Format Precision)");
2148         /* set_active will not trigger the callback when activating an active item! */
2149         recent.gui_time_precision = -1;
2150         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), FALSE);
2151         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), TRUE);
2152         break;
2153     case(TS_PREC_FIXED_SEC):
2154         menu = gtk_item_factory_get_widget(main_menu_factory,
2155             "/View/Time Display Format/Seconds:   0");
2156         recent.gui_time_precision = -1;
2157         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), TRUE);
2158         break;
2159     case(TS_PREC_FIXED_DSEC):
2160         menu = gtk_item_factory_get_widget(main_menu_factory,
2161             "/View/Time Display Format/Deciseconds:   0.1");
2162         recent.gui_time_precision = -1;
2163         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), TRUE);
2164         break;
2165     case(TS_PREC_FIXED_CSEC):
2166         menu = gtk_item_factory_get_widget(main_menu_factory,
2167             "/View/Time Display Format/Centiseconds:   0.12");
2168         recent.gui_time_precision = -1;
2169         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), TRUE);
2170         break;
2171     case(TS_PREC_FIXED_MSEC):
2172         menu = gtk_item_factory_get_widget(main_menu_factory,
2173             "/View/Time Display Format/Milliseconds:   0.123");
2174         recent.gui_time_precision = -1;
2175         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), TRUE);
2176         break;
2177     case(TS_PREC_FIXED_USEC):
2178         menu = gtk_item_factory_get_widget(main_menu_factory,
2179             "/View/Time Display Format/Microseconds:   0.123456");
2180         recent.gui_time_precision = -1;
2181         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), TRUE);
2182         break;
2183     case(TS_PREC_FIXED_NSEC):
2184         menu = gtk_item_factory_get_widget(main_menu_factory,
2185             "/View/Time Display Format/Nanoseconds:   0.123456789");
2186         recent.gui_time_precision = -1;
2187         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), TRUE);
2188         break;
2189     default:
2190         g_assert_not_reached();
2191     }
2192
2193     menu_colorize_changed(recent.packet_list_colorize);
2194 }
2195
2196
2197 gint
2198 popup_menu_handler(GtkWidget *widget, GdkEvent *event, gpointer data)
2199 {
2200     GtkWidget *menu = (GtkWidget *)data;
2201     GdkEventButton *event_button = NULL;
2202     gint row, column;
2203
2204     if(widget == NULL || event == NULL || data == NULL) {
2205         return FALSE;
2206     }
2207
2208     /*
2209      * If we ever want to make the menu differ based on what row
2210      * and/or column we're above, we'd use "eth_clist_get_selection_info()"
2211      * to find the row and column number for the coordinates; a CTree is,
2212      * I guess, like a CList with one column(?) and the expander widget
2213      * as a pixmap.
2214      */
2215     /* Check if we are on packet_list object */
2216     if (widget == g_object_get_data(G_OBJECT(popup_menu_object), E_MPACKET_LIST_KEY) &&
2217         ((GdkEventButton *)event)->button != 1) {
2218         if (packet_list_get_event_row_column(widget, (GdkEventButton *)event,
2219                                              &row, &column)) {
2220             g_object_set_data(G_OBJECT(popup_menu_object), E_MPACKET_LIST_ROW_KEY,
2221                             GINT_TO_POINTER(row));
2222             g_object_set_data(G_OBJECT(popup_menu_object), E_MPACKET_LIST_COL_KEY,
2223                             GINT_TO_POINTER(column));
2224             packet_list_set_selected_row(row);
2225         }
2226     }
2227
2228     /* Check if we are on tree_view object */
2229     if (widget == tree_view) {
2230         tree_view_select(widget, (GdkEventButton *) event);
2231     }
2232
2233     /* Check if we are on byte_view object */
2234     if(widget == get_notebook_bv_ptr(byte_nb_ptr)) {
2235         byte_view_select(widget, (GdkEventButton *) event);
2236     }
2237
2238     /* context menu handler (but the byte view notebook pages have their own handler) */
2239     if(event->type == GDK_BUTTON_PRESS && widget != byte_nb_ptr) {
2240         event_button = (GdkEventButton *) event;
2241
2242         /* To qoute the "Gdk Event Structures" doc:
2243          * "Normally button 1 is the left mouse button, 2 is the middle button, and 3 is the right button" */
2244         if(event_button->button == 3) {
2245             gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL,
2246                            event_button->button,
2247                            event_button->time);
2248             g_signal_stop_emission_by_name(widget, "button_press_event");
2249             return TRUE;
2250         }
2251     }
2252     /* GDK_2BUTTON_PRESS is a doubleclick -> expand/collapse tree row */
2253     /* GTK version 1 seems to be doing this automatically */
2254     if (widget == tree_view && event->type == GDK_2BUTTON_PRESS) {
2255         GtkTreePath      *path;
2256
2257         if (gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(widget),
2258                                           (gint) (((GdkEventButton *)event)->x),
2259                                           (gint) (((GdkEventButton *)event)->y),
2260                                           &path, NULL, NULL, NULL))
2261         {
2262             if (gtk_tree_view_row_expanded(GTK_TREE_VIEW(widget), path))
2263                 gtk_tree_view_collapse_row(GTK_TREE_VIEW(widget), path);
2264             else
2265                 gtk_tree_view_expand_row(GTK_TREE_VIEW(widget), path,
2266                                          FALSE);
2267             gtk_tree_path_free(path);
2268         }
2269     }
2270     return FALSE;
2271 }
2272
2273 /* Enable or disable menu items based on whether you have a capture file
2274    you've finished reading and, if you have one, whether it's been saved
2275    and whether it could be saved except by copying the raw packet data. */
2276 void
2277 set_menus_for_capture_file(capture_file *cf)
2278 {
2279   if (cf == NULL) {
2280     /* We have no capture file */
2281     set_menu_sensitivity(main_menu_factory, "/File/Merge...", FALSE);
2282     set_menu_sensitivity(main_menu_factory, "/File/Close", FALSE);
2283     set_menu_sensitivity(main_menu_factory, "/File/Save", FALSE);
2284     set_menu_sensitivity(main_menu_factory, "/File/Save As...", FALSE);
2285     set_menu_sensitivity(main_menu_factory, "/File/Export", FALSE);
2286     set_menu_sensitivity(main_menu_factory, "/View/Reload", FALSE);
2287     set_toolbar_for_capture_file(FALSE);
2288     set_toolbar_for_unsaved_capture_file(FALSE);
2289   } else {
2290     set_menu_sensitivity(main_menu_factory, "/File/Merge...", TRUE);
2291     set_menu_sensitivity(main_menu_factory, "/File/Close", TRUE);
2292     set_menu_sensitivity(main_menu_factory, "/File/Save", !cf->user_saved);
2293     /*
2294      * "Save As..." works only if we can write the file out in at least
2295      * one format (so we can save the whole file or just a subset) or
2296      * if we have an unsaved capture (so writing the whole file out
2297      * with a raw data copy makes sense).
2298      */
2299     set_menu_sensitivity(main_menu_factory, "/File/Save As...",
2300         cf_can_save_as(cf) || !cf->user_saved);
2301     set_menu_sensitivity(main_menu_factory, "/File/Export", TRUE);
2302     set_menu_sensitivity(main_menu_factory, "/View/Reload", TRUE);
2303     set_toolbar_for_unsaved_capture_file(!cf->user_saved);
2304     set_toolbar_for_capture_file(TRUE);
2305   }
2306 }
2307
2308 /* Enable or disable menu items based on whether there's a capture in
2309    progress. */
2310 void
2311 set_menus_for_capture_in_progress(gboolean capture_in_progress)
2312 {
2313   set_menu_sensitivity(main_menu_factory, "/File/Open...",
2314       !capture_in_progress);
2315   set_menu_sensitivity(main_menu_factory, "/File/Open Recent",
2316       !capture_in_progress);
2317   set_menu_sensitivity(main_menu_factory, "/File/Export",
2318        capture_in_progress);
2319 #ifdef HAVE_LIBPCAP
2320   set_menu_sensitivity(main_menu_factory, "/Capture/Options...",
2321       !capture_in_progress);
2322   set_menu_sensitivity(main_menu_factory, "/Capture/Start",
2323       !capture_in_progress);
2324   set_menu_sensitivity(main_menu_factory, "/Capture/Stop",
2325       capture_in_progress);
2326   set_menu_sensitivity(main_menu_factory, "/Capture/Restart",
2327       capture_in_progress);
2328   set_toolbar_for_capture_in_progress(capture_in_progress);
2329
2330   set_capture_if_dialog_for_capture_in_progress(capture_in_progress);
2331 #endif /* HAVE_LIBPCAP */
2332 }
2333
2334 /* Enable or disable menu items based on whether you have some captured
2335    packets. */
2336 static gboolean
2337 walk_menu_tree_for_captured_packets(GList *node,
2338     gboolean have_captured_packets)
2339 {
2340         gboolean    is_enabled;
2341         GList       *child;
2342         menu_item_t *node_data = node->data;
2343
2344         /*
2345          * Is this a leaf node or an interior node?
2346          */
2347         if (node_data->children == NULL) {
2348                 /*
2349                  * It's a leaf node.
2350                  *
2351                  * If it has no "selected_packet_enabled()" or
2352                  * "selected_tree_row_enabled()" routines, we enable
2353                  * it.  This allows tap windows to be popped up even
2354                  * if you have no capture file; this is done to let
2355                  * the user pop up multiple tap windows before reading
2356                  * in a capture file, so that they can be processed in
2357                  * parallel while the capture file is being read rather
2358                  * than one at at time as you pop up the windows, and to
2359                  * let the user pop up tap windows before starting an
2360                  * "Update list of packets in real time" capture, so that
2361                  * the statistics can be displayed while the capture is
2362                  * in progress.
2363                  *
2364                  * If it has either of those routines, we disable it for
2365                  * now - as long as, when a capture is first available,
2366                  * we don't get called after a packet or tree row is
2367                  * selected, that's OK.
2368                  * XXX - that should be done better.
2369                  */
2370                 if (node_data->selected_packet_enabled == NULL &&
2371                     node_data->selected_tree_row_enabled == NULL)
2372                         node_data->enabled = TRUE;
2373                 else
2374                         node_data->enabled = FALSE;
2375         } else {
2376                 /*
2377                  * It's an interior node; call
2378                  * "walk_menu_tree_for_captured_packets()" on all its
2379                  * children and, if any of them are enabled, enable
2380                  * this node, otherwise disable it.
2381                  *
2382                  * XXX - should we just leave all interior nodes enabled?
2383                  * Which is a better UI choice?
2384                  */
2385                 is_enabled = FALSE;
2386                 for (child = node_data->children; child != NULL; child =
2387                     child->next) {
2388                         if (walk_menu_tree_for_captured_packets(child,
2389                             have_captured_packets))
2390                                 is_enabled = TRUE;
2391                 }
2392                 node_data->enabled = is_enabled;
2393         }
2394
2395         /*
2396          * The root node doesn't correspond to a menu tree item; it
2397          * has a null name pointer.
2398          */
2399         if (node_data->name != NULL) {
2400                 set_menu_sensitivity(main_menu_factory, node_data->name,
2401                     node_data->enabled);
2402         }
2403         return node_data->enabled;
2404 }
2405
2406 void
2407 set_menus_for_captured_packets(gboolean have_captured_packets)
2408 {
2409   set_menu_sensitivity(main_menu_factory, "/File/Print...",
2410       have_captured_packets);
2411   set_menu_sensitivity(packet_list_menu_factory, "/Print...",
2412       have_captured_packets);
2413   set_menu_sensitivity(main_menu_factory, "/Edit/Find Packet...",
2414       have_captured_packets);
2415   set_menu_sensitivity(main_menu_factory, "/Edit/Find Next",
2416       have_captured_packets);
2417   set_menu_sensitivity(main_menu_factory, "/Edit/Find Previous",
2418       have_captured_packets);
2419   set_menu_sensitivity(main_menu_factory, "/View/Zoom In",
2420       have_captured_packets);
2421   set_menu_sensitivity(main_menu_factory, "/View/Zoom Out",
2422       have_captured_packets);
2423   set_menu_sensitivity(main_menu_factory, "/View/Normal Size",
2424       have_captured_packets);
2425   set_menu_sensitivity(main_menu_factory, "/Go/Go to Packet...",
2426       have_captured_packets);
2427   set_menu_sensitivity(main_menu_factory, "/Go/Previous Packet",
2428       have_captured_packets);
2429   set_menu_sensitivity(main_menu_factory, "/Go/Next Packet",
2430       have_captured_packets);
2431   set_menu_sensitivity(main_menu_factory, "/Go/First Packet",
2432       have_captured_packets);
2433   set_menu_sensitivity(main_menu_factory, "/Go/Last Packet",
2434       have_captured_packets);
2435   set_menu_sensitivity(main_menu_factory, "/Statistics/Summary",
2436       have_captured_packets);
2437   set_menu_sensitivity(main_menu_factory, "/Statistics/Protocol Hierarchy",
2438       have_captured_packets);
2439
2440   walk_menu_tree_for_captured_packets(tap_menu_tree_root,
2441       have_captured_packets);
2442   set_toolbar_for_captured_packets(have_captured_packets);
2443 }
2444
2445 /* Enable or disable menu items based on whether a packet is selected and,
2446    if so, on the properties of the packet. */
2447 static gboolean
2448 walk_menu_tree_for_selected_packet(GList *node, frame_data *fd,
2449     epan_dissect_t *edt)
2450 {
2451         gboolean is_enabled;
2452         GList *child;
2453         menu_item_t *node_data = node->data;
2454
2455         /*
2456          * Is this a leaf node or an interior node?
2457          */
2458         if (node_data->children == NULL) {
2459                 /*
2460                  * It's a leaf node.
2461                  *
2462                  * If it has no "selected_packet_enabled()" routine,
2463                  * leave its enabled/disabled status alone - it
2464                  * doesn't depend on whether we have a packet selected
2465                  * or not or on the selected packet.
2466                  *
2467                  * If it has a "selected_packet_enabled()" routine,
2468                  * call it and set the item's enabled/disabled status
2469                  * based on its return value.
2470                  */
2471                 if (node_data->selected_packet_enabled != NULL)
2472                         node_data->enabled = node_data->selected_packet_enabled(fd, edt, node_data->callback_data);
2473         } else {
2474                 /*
2475                  * It's an interior node; call
2476                  * "walk_menu_tree_for_selected_packet()" on all its
2477                  * children and, if any of them are enabled, enable
2478                  * this node, otherwise disable it.
2479                  *
2480                  * XXX - should we just leave all interior nodes enabled?
2481                  * Which is a better UI choice?
2482                  */
2483                 is_enabled = FALSE;
2484                 for (child = node_data->children; child != NULL; child =
2485                     child->next) {
2486                         if (walk_menu_tree_for_selected_packet(child, fd, edt))
2487                                 is_enabled = TRUE;
2488                 }
2489                 node_data->enabled = is_enabled;
2490         }
2491
2492         /*
2493          * The root node doesn't correspond to a menu tree item; it
2494          * has a null name pointer.
2495          */
2496         if (node_data->name != NULL) {
2497                 set_menu_sensitivity(main_menu_factory, node_data->name,
2498                     node_data->enabled);
2499         }
2500         return node_data->enabled;
2501 }
2502
2503 gboolean
2504 packet_is_ssl(epan_dissect_t* edt)
2505 {
2506   GPtrArray* array;
2507   int ssl_id;
2508   gboolean is_ssl;
2509
2510   if (!edt || !edt->tree)
2511       return FALSE;
2512   ssl_id = proto_get_id_by_filter_name("ssl");
2513   if (ssl_id < 0)
2514       return FALSE;
2515   array = proto_find_finfo(edt->tree, ssl_id);
2516   is_ssl = (array->len > 0) ? TRUE : FALSE;
2517   g_ptr_array_free(array, FALSE);
2518   return is_ssl;
2519 }
2520
2521 void
2522 set_menus_for_selected_packet(capture_file *cf)
2523 {
2524   gboolean is_ssl = packet_is_ssl(cf->edt);
2525   set_menu_sensitivity(main_menu_factory, "/Edit/Mark Packet (toggle)",
2526       cf->current_frame != NULL);
2527   set_menu_sensitivity(packet_list_menu_factory, "/Mark Packet (toggle)",
2528       cf->current_frame != NULL);
2529   set_menu_sensitivity(main_menu_factory, "/Edit/Find Next Mark",
2530       cf->current_frame != NULL);
2531   set_menu_sensitivity(main_menu_factory, "/Edit/Find Previous Mark",
2532       cf->current_frame != NULL);
2533   set_menu_sensitivity(main_menu_factory, "/Edit/Mark All Packets",
2534       cf->current_frame != NULL);
2535   set_menu_sensitivity(main_menu_factory, "/Edit/Unmark All Packets",
2536       cf->current_frame != NULL);
2537   set_menu_sensitivity(main_menu_factory, "/Edit/Set Time Reference (toggle)",
2538       cf->current_frame != NULL);
2539   set_menu_sensitivity(packet_list_menu_factory, "/Set Time Reference (toggle)",
2540       cf->current_frame != NULL);
2541   set_menu_sensitivity(main_menu_factory, "/Edit/Find Next Reference",
2542       cf->current_frame != NULL);
2543   set_menu_sensitivity(main_menu_factory, "/Edit/Find Previous Reference",
2544       cf->current_frame != NULL);
2545   set_menu_sensitivity(main_menu_factory, "/View/Resize All Columns",
2546       cf->current_frame != NULL);
2547   set_menu_sensitivity(main_menu_factory, "/View/Collapse All",
2548       cf->current_frame != NULL);
2549   set_menu_sensitivity(tree_view_menu_factory, "/Collapse All",
2550       cf->current_frame != NULL);
2551   set_menu_sensitivity(main_menu_factory, "/View/Expand All",
2552       cf->current_frame != NULL);
2553   set_menu_sensitivity(tree_view_menu_factory, "/Expand All",
2554       cf->current_frame != NULL);
2555   set_menu_sensitivity(main_menu_factory, "/View/Colorize Conversation",
2556       cf->current_frame != NULL);
2557   set_menu_sensitivity(main_menu_factory, "/View/Reset Coloring 1-10",
2558       tmp_color_filters_used());
2559   set_menu_sensitivity(main_menu_factory, "/View/Show Packet in New Window",
2560       cf->current_frame != NULL);
2561   set_menu_sensitivity(packet_list_menu_factory, "/Show Packet in New Window",
2562       cf->current_frame != NULL);
2563   set_menu_sensitivity(packet_list_menu_factory, "/SCTP",
2564       cf->current_frame != NULL ? (cf->edt->pi.ipproto == IP_PROTO_SCTP) : FALSE);
2565   set_menu_sensitivity(main_menu_factory, "/Analyze/Follow TCP Stream",
2566       cf->current_frame != NULL ? (cf->edt->pi.ipproto == IP_PROTO_TCP) : FALSE);
2567   set_menu_sensitivity(packet_list_menu_factory, "/Follow TCP Stream",
2568       cf->current_frame != NULL ? (cf->edt->pi.ipproto == IP_PROTO_TCP) : FALSE);
2569   set_menu_sensitivity(tree_view_menu_factory, "/Follow TCP Stream",
2570       cf->current_frame != NULL ? (cf->edt->pi.ipproto == IP_PROTO_TCP) : FALSE);
2571   set_menu_sensitivity(main_menu_factory, "/Analyze/Follow UDP Stream",
2572       cf->current_frame != NULL ? (cf->edt->pi.ipproto == IP_PROTO_UDP) : FALSE);
2573   set_menu_sensitivity(packet_list_menu_factory, "/Follow UDP Stream",
2574       cf->current_frame != NULL ? (cf->edt->pi.ipproto == IP_PROTO_UDP) : FALSE);
2575   set_menu_sensitivity(tree_view_menu_factory, "/Follow UDP Stream",
2576       cf->current_frame != NULL ? (cf->edt->pi.ipproto == IP_PROTO_UDP) : FALSE);
2577   set_menu_sensitivity(main_menu_factory, "/Analyze/Follow SSL Stream",
2578       cf->current_frame != NULL ? is_ssl : FALSE);
2579   set_menu_sensitivity(packet_list_menu_factory, "/Follow SSL Stream",
2580       cf->current_frame != NULL ? is_ssl : FALSE);
2581   set_menu_sensitivity(tree_view_menu_factory, "/Follow SSL Stream",
2582       cf->current_frame != NULL ? is_ssl : FALSE);
2583   set_menu_sensitivity(packet_list_menu_factory, "/Conversation Filter",
2584       cf->current_frame != NULL);
2585   set_menu_sensitivity(packet_list_menu_factory, "/Conversation Filter/Ethernet",
2586       cf->current_frame != NULL ? (cf->edt->pi.dl_src.type == 1) : FALSE);
2587   set_menu_sensitivity(packet_list_menu_factory, "/Conversation Filter/IP",
2588       cf->current_frame != NULL ? (cf->edt->pi.ethertype == 0x800) : FALSE);
2589   set_menu_sensitivity(packet_list_menu_factory, "/Conversation Filter/TCP",
2590       cf->current_frame != NULL ? (cf->edt->pi.ipproto == IP_PROTO_TCP) : FALSE);
2591   set_menu_sensitivity(packet_list_menu_factory, "/Conversation Filter/UDP",
2592       cf->current_frame != NULL ? (cf->edt->pi.ipproto == IP_PROTO_UDP) : FALSE);
2593   set_menu_sensitivity(packet_list_menu_factory, "/Conversation Filter/PN-CBA Server",
2594       cf->current_frame != NULL ? (cf->edt->pi.profinet_type != 0 && cf->edt->pi.profinet_type < 10) : FALSE);
2595   set_menu_sensitivity(packet_list_menu_factory, "/Colorize Conversation",
2596       cf->current_frame != NULL);
2597   set_menu_sensitivity(packet_list_menu_factory, "/Colorize Conversation/Ethernet",
2598       cf->current_frame != NULL ? (cf->edt->pi.dl_src.type == 1) : FALSE);
2599   set_menu_sensitivity(packet_list_menu_factory, "/Colorize Conversation/IP",
2600       cf->current_frame != NULL ? (cf->edt->pi.ethertype == 0x800) : FALSE);
2601   set_menu_sensitivity(packet_list_menu_factory, "/Colorize Conversation/TCP",
2602       cf->current_frame != NULL ? (cf->edt->pi.ipproto == IP_PROTO_TCP) : FALSE);
2603   set_menu_sensitivity(packet_list_menu_factory, "/Colorize Conversation/UDP",
2604       cf->current_frame != NULL ? (cf->edt->pi.ipproto == IP_PROTO_UDP) : FALSE);
2605   set_menu_sensitivity(packet_list_menu_factory, "/Colorize Conversation/PN-CBA Server",
2606       cf->current_frame != NULL ? (cf->edt->pi.profinet_type != 0 && cf->edt->pi.profinet_type < 10) : FALSE);
2607   set_menu_sensitivity(main_menu_factory, "/Analyze/Decode As...",
2608       cf->current_frame != NULL && decode_as_ok());
2609   set_menu_sensitivity(packet_list_menu_factory, "/Decode As...",
2610       cf->current_frame != NULL && decode_as_ok());
2611   set_menu_sensitivity(tree_view_menu_factory, "/Decode As...",
2612       cf->current_frame != NULL && decode_as_ok());
2613   set_menu_sensitivity(main_menu_factory, "/View/Name Resolution/Resolve Name",
2614       cf->current_frame != NULL && (g_resolv_flags & RESOLV_ALL_ADDRS) != RESOLV_ALL_ADDRS);
2615   set_menu_sensitivity(tree_view_menu_factory, "/Resolve Name",
2616       cf->current_frame != NULL && (g_resolv_flags & RESOLV_ALL_ADDRS) != RESOLV_ALL_ADDRS);
2617   set_menu_sensitivity(packet_list_menu_factory, "/Copy",
2618       cf->current_frame != NULL);
2619   set_menu_sensitivity(packet_list_menu_factory, "/Apply as Filter",
2620       cf->current_frame != NULL);
2621   set_menu_sensitivity(packet_list_menu_factory, "/Prepare a Filter",
2622       cf->current_frame != NULL);
2623   set_menu_sensitivity(main_menu_factory, "/Tools/Firewall ACL Rules",
2624       cf->current_frame != NULL);
2625
2626   walk_menu_tree_for_selected_packet(tap_menu_tree_root, cf->current_frame,
2627       cf->edt);
2628 }
2629
2630 /* Enable or disable menu items based on whether a tree row is selected
2631    and, if so, on the properties of the tree row. */
2632 static gboolean
2633 walk_menu_tree_for_selected_tree_row(GList *node, field_info *fi)
2634 {
2635         gboolean is_enabled;
2636         GList *child;
2637         menu_item_t *node_data = node->data;
2638
2639         /*
2640          * Is this a leaf node or an interior node?
2641          */
2642         if (node_data->children == NULL) {
2643                 /*
2644                  * It's a leaf node.
2645                  *
2646                  * If it has no "selected_tree_row_enabled()" routine,
2647                  * leave its enabled/disabled status alone - it
2648                  * doesn't depend on whether we have a tree row selected
2649                  * or not or on the selected tree row.
2650                  *
2651                  * If it has a "selected_tree_row_enabled()" routine,
2652                  * call it and set the item's enabled/disabled status
2653                  * based on its return value.
2654                  */
2655                 if (node_data->selected_tree_row_enabled != NULL)
2656                         node_data->enabled = node_data->selected_tree_row_enabled(fi, node_data->callback_data);
2657         } else {
2658                 /*
2659                  * It's an interior node; call
2660                  * "walk_menu_tree_for_selected_tree_row()" on all its
2661                  * children and, if any of them are enabled, enable
2662                  * this node, otherwise disable it.
2663                  *
2664                  * XXX - should we just leave all interior nodes enabled?
2665                  * Which is a better UI choice?
2666                  */
2667                 is_enabled = FALSE;
2668                 for (child = node_data->children; child != NULL; child =
2669                     child->next) {
2670                         if (walk_menu_tree_for_selected_tree_row(child, fi))
2671                                 is_enabled = TRUE;
2672                 }
2673                 node_data->enabled = is_enabled;
2674         }
2675
2676         /*
2677          * The root node doesn't correspond to a menu tree item; it
2678          * has a null name pointer.
2679          */
2680         if (node_data->name != NULL) {
2681                 set_menu_sensitivity(main_menu_factory, node_data->name,
2682                     node_data->enabled);
2683         }
2684         return node_data->enabled;
2685 }
2686
2687 void
2688 set_menus_for_selected_tree_row(capture_file *cf)
2689 {
2690   gboolean properties;
2691   gint id;
2692
2693   if (cf->finfo_selected != NULL) {
2694         header_field_info *hfinfo = cf->finfo_selected->hfinfo;
2695         if (hfinfo->parent == -1) {
2696           properties = prefs_is_registered_protocol(hfinfo->abbrev);
2697           id = (hfinfo->type == FT_PROTOCOL) ? proto_get_id((protocol_t *)hfinfo->strings) : -1;
2698         } else {
2699           properties = prefs_is_registered_protocol(proto_registrar_get_abbrev(hfinfo->parent));
2700           id = hfinfo->parent;
2701         }
2702         set_menu_sensitivity(main_menu_factory,
2703           "/File/Export/Selected Packet Bytes...", TRUE);
2704         set_menu_sensitivity(main_menu_factory,
2705           "/Go/Go to Corresponding Packet", hfinfo->type == FT_FRAMENUM);
2706         set_menu_sensitivity(tree_view_menu_factory,
2707           "/Go to Corresponding Packet", hfinfo->type == FT_FRAMENUM);
2708         set_menu_sensitivity(main_menu_factory, "/Edit/Copy",
2709           proto_can_match_selected(cf->finfo_selected, cf->edt));
2710         set_menu_sensitivity(tree_view_menu_factory, "/Copy",
2711           TRUE);
2712         set_menu_sensitivity(tree_view_menu_factory, "/Copy/As Filter",
2713           proto_can_match_selected(cf->finfo_selected, cf->edt));
2714         set_menu_sensitivity(main_menu_factory, "/Analyze/Apply as Filter",
2715           proto_can_match_selected(cf->finfo_selected, cf->edt));
2716         set_menu_sensitivity(tree_view_menu_factory, "/Apply as Filter",
2717           proto_can_match_selected(cf->finfo_selected, cf->edt));
2718         set_menu_sensitivity(main_menu_factory, "/Analyze/Prepare a Filter",
2719           proto_can_match_selected(cf->finfo_selected, cf->edt));
2720         set_menu_sensitivity(tree_view_menu_factory, "/Prepare a Filter",
2721           proto_can_match_selected(cf->finfo_selected, cf->edt));
2722         set_menu_sensitivity(tree_view_menu_factory, "/Colorize with Filter",
2723           proto_can_match_selected(cf->finfo_selected, cf->edt));
2724         set_menu_sensitivity(tree_view_menu_factory, "/Protocol Preferences...",
2725           properties);
2726         set_menu_sensitivity(tree_view_menu_factory, "/Disable Protocol...",
2727           (id == -1) ? FALSE : proto_can_toggle_protocol(id));
2728         set_menu_sensitivity(main_menu_factory, "/View/Expand Subtrees", cf->finfo_selected->tree_type != -1);
2729         set_menu_sensitivity(tree_view_menu_factory, "/Expand Subtrees", cf->finfo_selected->tree_type != -1);
2730         set_menu_sensitivity(tree_view_menu_factory, "/Wiki Protocol Page",
2731           TRUE);
2732         set_menu_sensitivity(tree_view_menu_factory, "/Filter Field Reference",
2733           TRUE);
2734   } else {
2735         set_menu_sensitivity(main_menu_factory,
2736           "/File/Export/Selected Packet Bytes...", FALSE);
2737         set_menu_sensitivity(main_menu_factory,
2738           "/Go/Go to Corresponding Packet", FALSE);
2739         set_menu_sensitivity(tree_view_menu_factory,
2740           "/Go to Corresponding Packet", FALSE);
2741         set_menu_sensitivity(main_menu_factory, "/Edit/Copy", FALSE);
2742         set_menu_sensitivity(tree_view_menu_factory, "/Copy", FALSE);
2743         set_menu_sensitivity(main_menu_factory, "/Analyze/Apply as Filter", FALSE);
2744         set_menu_sensitivity(tree_view_menu_factory, "/Apply as Filter", FALSE);
2745         set_menu_sensitivity(main_menu_factory, "/Analyze/Prepare a Filter", FALSE);
2746         set_menu_sensitivity(tree_view_menu_factory, "/Prepare a Filter", FALSE);
2747         set_menu_sensitivity(tree_view_menu_factory, "/Colorize with Filter", FALSE);
2748         set_menu_sensitivity(tree_view_menu_factory, "/Protocol Preferences...",
2749           FALSE);
2750         set_menu_sensitivity(tree_view_menu_factory, "/Disable Protocol...", FALSE);
2751         set_menu_sensitivity(main_menu_factory, "/View/Expand Subtrees", FALSE);
2752         set_menu_sensitivity(tree_view_menu_factory, "/Expand Subtrees", FALSE);
2753         set_menu_sensitivity(tree_view_menu_factory, "/Wiki Protocol Page",
2754           FALSE);
2755         set_menu_sensitivity(tree_view_menu_factory, "/Filter Field Reference",
2756           FALSE);
2757   }
2758
2759   walk_menu_tree_for_selected_tree_row(tap_menu_tree_root, cf->finfo_selected);
2760 }
2761
2762 void set_menus_for_packet_history(gboolean back_history, gboolean forward_history) {
2763
2764   set_menu_sensitivity(main_menu_factory, "/Go/Back", back_history);
2765   set_menu_sensitivity(main_menu_factory, "/Go/Forward", forward_history);
2766
2767   set_toolbar_for_packet_history(back_history, forward_history);
2768 }
2769
2770
2771 void set_menus_for_file_set(gboolean file_set, gboolean previous_file, gboolean next_file) {
2772
2773   set_menu_sensitivity(main_menu_factory, "/File/File Set/List Files", file_set);
2774   set_menu_sensitivity(main_menu_factory, "/File/File Set/Previous File", previous_file);
2775   set_menu_sensitivity(main_menu_factory, "/File/File Set/Next File", next_file);
2776 }