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