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