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