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