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