e4c94e6d79827f8d6ea83a46dc8aeb327bc22159
[obnox/wireshark/wip.git] / gtk / menu.c
1 /* menu.c
2  * Menu routines
3  *
4  * $Id: menu.c,v 1.21 2000/01/25 03:48:16 gerald Exp $
5  *
6  * Ethereal - Network traffic analyzer
7  * By Gerald Combs <gerald@zing.org>
8  * Copyright 1998 Gerald Combs
9  *
10  * 
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  * 
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  * 
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
24  */
25
26 #ifdef HAVE_CONFIG_H
27 # include "config.h"
28 #endif
29
30 #include <gtk/gtk.h>
31 #include <glib.h>
32
33 #include <string.h>
34 #include <stdio.h>
35
36 #ifdef HAVE_SYS_TYPES_H
37 # include <sys/types.h>
38 #endif
39
40 #include "../menu.h"
41
42 #include "main.h"
43 #include "menu.h"
44 #include "packet.h"
45 #include "capture_dlg.h"
46 #include "find_dlg.h"
47 #include "goto_dlg.h"
48 #include "summary_dlg.h"
49 #include "display_opts.h"
50 #include "prefs_dlg.h"
51 #include "print.h"
52 #include "follow.h"
53 #include "colors.h"
54 #include "keys.h"
55 #include "plugins.h"
56
57 #define GTK_MENU_FUNC(a) ((GtkItemFactoryCallback)(a))
58
59 static void menus_init(void);
60 static void set_menu_sensitivity (gchar *, gint);
61
62 /* This is the GtkItemFactoryEntry structure used to generate new menus.
63        Item 1: The menu path. The letter after the underscore indicates an
64                accelerator key once the menu is open.
65        Item 2: The accelerator key for the entry
66        Item 3: The callback function.
67        Item 4: The callback action.  This changes the parameters with
68                which the function is called.  The default is 0.
69        Item 5: The item type, used to define what kind of an item it is.
70                Here are the possible values:
71
72                NULL               -> "<Item>"
73                ""                 -> "<Item>"
74                "<Title>"          -> create a title item
75                "<Item>"           -> create a simple item
76                "<CheckItem>"      -> create a check item
77                "<ToggleItem>"     -> create a toggle item
78                "<RadioItem>"      -> create a radio item
79                <path>             -> path of a radio item to link against
80                "<Separator>"      -> create a separator
81                "<Branch>"         -> create an item to hold sub items (optional)
82                "<LastBranch>"     -> create a right justified branch 
83     */
84
85 /* main menu */
86 static GtkItemFactoryEntry menu_items[] =
87 {
88   {"/_File", NULL, NULL, 0, "<Branch>" },
89   {"/File/_Open...", "<control>O", GTK_MENU_FUNC(file_open_cmd_cb), 0, NULL},
90   {"/File/_Close", "<control>W", GTK_MENU_FUNC(file_close_cmd_cb), 0, NULL},
91   {"/File/_Save", "<control>S", GTK_MENU_FUNC(file_save_cmd_cb), 0, NULL},
92   {"/File/Save _As...", NULL, GTK_MENU_FUNC(file_save_as_cmd_cb), 0, NULL},
93   {"/File/_Reload", "<control>R", GTK_MENU_FUNC(file_reload_cmd_cb), 0, NULL},
94   {"/File/<separator>", NULL, NULL, 0, "<Separator>"},
95   {"/File/Print...", NULL, GTK_MENU_FUNC(file_print_cmd_cb), 0, NULL},
96   {"/File/Print Pac_ket", "<control>P", GTK_MENU_FUNC(file_print_packet_cmd_cb), 0, NULL},
97   {"/File/<separator>", NULL, NULL, 0, "<Separator>"},
98   {"/File/_Quit", "<control>Q", GTK_MENU_FUNC(file_quit_cmd_cb), 0, NULL},
99   {"/_Edit", NULL, NULL, 0, "<Branch>" },
100   {"/Edit/Cut", "<control>X", NULL, 0, NULL},
101   {"/Edit/Copy", "<control>C", NULL, 0, NULL},
102   {"/Edit/Paste", "<control>V", NULL, 0, NULL},
103   {"/Edit/<separator>", NULL, NULL, 0, "<Separator>"},
104   {"/Edit/_Find Frame...", "<control>F", GTK_MENU_FUNC(find_frame_cb), 0, NULL},
105   {"/Edit/_Go To Frame...", "<control>G", GTK_MENU_FUNC(goto_frame_cb), 0, NULL},
106   {"/Edit/<separator>", NULL, NULL, 0, "<Separator>"},
107   {"/Edit/_Preferences...", NULL, GTK_MENU_FUNC(prefs_cb), E_PR_PG_NONE, NULL},
108   {"/Edit/_Filters...", NULL, GTK_MENU_FUNC(filter_dialog_cb), 0, NULL},
109 #ifdef HAVE_LIBPCAP
110   {"/_Capture", NULL, NULL, 0, "<Branch>" },
111   {"/Capture/_Start...", "<control>K", GTK_MENU_FUNC(capture_prep_cb), 0, NULL},
112 #endif
113   {"/_Display", NULL, NULL, 0, "<Branch>" },
114   {"/Display/_Options...", NULL, GTK_MENU_FUNC(display_opt_cb), 0, NULL},
115   {"/Display/_Match Selected", NULL, GTK_MENU_FUNC(match_selected_cb), 0, NULL},
116   {"/Display/_Colorize Display...", NULL, GTK_MENU_FUNC(color_display_cb), 0, NULL},
117   {"/Display/_Find Frame...", NULL, GTK_MENU_FUNC(find_frame_cb), 0, NULL},
118   {"/Display/_Go To Frame...", NULL, GTK_MENU_FUNC(goto_frame_cb), 0, NULL},
119   {"/Display/Collapse _All", NULL, GTK_MENU_FUNC(collapse_all_cb), 0, NULL},
120   {"/Display/_Expand All", NULL, GTK_MENU_FUNC(expand_all_cb), 0, NULL},
121   {"/_Tools", NULL, NULL, 0, "<Branch>" },
122 #ifdef HAVE_PLUGINS
123   {"/Tools/_Plugins...", NULL, GTK_MENU_FUNC(tools_plugins_cmd_cb), 0, NULL},
124 #endif
125   {"/Tools/_Follow TCP Stream", NULL, GTK_MENU_FUNC(follow_stream_cb), 0, NULL},
126 /*  {"/Tools/Graph", NULL, NULL, 0, NULL}, future use */
127   {"/Tools/_Summary", NULL, GTK_MENU_FUNC(summary_open_cb), 0, NULL},
128   {"/_Help", NULL, NULL, 0, "<LastBranch>" },
129   {"/Help/_About Ethereal...", NULL, GTK_MENU_FUNC(about_ethereal), 0, NULL}
130 };
131
132 /* calculate the number of menu_items */
133 static int nmenu_items = sizeof(menu_items) / sizeof(menu_items[0]);
134
135 /* packet list popup */
136 static GtkItemFactoryEntry packet_list_menu_items[] =
137 {
138         {"/Match Selected", NULL, GTK_MENU_FUNC(match_selected_cb), 0, NULL},
139         {"/Follow TCP Stream", NULL, GTK_MENU_FUNC(follow_stream_cb), 0, NULL},
140         {"/Filters...", NULL, GTK_MENU_FUNC(filter_dialog_cb), 0, NULL},
141         {"/<separator>", NULL, NULL, 0, "<Separator>"},
142         {"/Colorize Display...", NULL, GTK_MENU_FUNC(color_display_cb), 0, NULL},
143         {"/Print...", NULL, GTK_MENU_FUNC(file_print_cmd_cb), 0, NULL},
144         {"/Print Packet", NULL, GTK_MENU_FUNC(file_print_packet_cmd_cb), 0, NULL},
145 };
146
147 static GtkItemFactoryEntry tree_view_menu_items[] =
148 {
149         {"/Match Selected", NULL, GTK_MENU_FUNC(match_selected_cb), 0, NULL},
150         {"/Follow TCP Stream", NULL, GTK_MENU_FUNC(follow_stream_cb), 0, NULL},
151         {"/Filters...", NULL, GTK_MENU_FUNC(filter_dialog_cb), 0, NULL},
152         {"/<separator>", NULL, NULL, 0, "<Separator>"},
153         {"/Collapse All", NULL, GTK_MENU_FUNC(collapse_all_cb), 0, NULL},
154         {"/Expand All", NULL, GTK_MENU_FUNC(expand_all_cb), 0, NULL}
155 };
156
157
158 static int initialize = TRUE;
159 static GtkItemFactory *factory = NULL;
160 static GtkItemFactory *packet_list_menu_factory = NULL;
161 static GtkItemFactory *tree_view_menu_factory = NULL;
162
163 static GSList *popup_menu_list = NULL;
164
165 static GtkAccelGroup *grp;
166
167 void
168 get_main_menu(GtkWidget ** menubar, GtkAccelGroup ** table) {
169
170   grp = gtk_accel_group_new();
171
172   if (initialize) {
173     popup_menu_object = gtk_widget_new(GTK_TYPE_WIDGET, NULL);
174     menus_init();
175   }
176
177   if (menubar)
178     *menubar = factory->widget;
179
180   if (table)
181     *table = grp;
182 }
183
184 static void
185 menus_init(void) {
186
187   if (initialize) {
188     initialize = FALSE;
189
190     /* popup */
191
192     packet_list_menu_factory = gtk_item_factory_new(GTK_TYPE_MENU, "<main>", NULL);
193     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, NULL, 2);
194     gtk_object_set_data(GTK_OBJECT(popup_menu_object), PM_PACKET_LIST_KEY, packet_list_menu_factory->widget);
195     popup_menu_list = g_slist_append((GSList *)popup_menu_list, packet_list_menu_factory);
196
197     tree_view_menu_factory = gtk_item_factory_new(GTK_TYPE_MENU, "<main>", NULL);
198     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, NULL, 2);
199     gtk_object_set_data(GTK_OBJECT(popup_menu_object), PM_TREE_VIEW_KEY, tree_view_menu_factory->widget);
200     popup_menu_list = g_slist_append((GSList *)popup_menu_list, tree_view_menu_factory);
201     
202     factory = gtk_item_factory_new(GTK_TYPE_MENU_BAR, "<main>", grp);
203     gtk_item_factory_create_items_ac(factory, nmenu_items, menu_items, NULL,2);
204     set_menus_for_unsaved_capture_file(FALSE);
205     set_menus_for_capture_file(FALSE);
206     set_menu_sensitivity("/Edit/Cut", FALSE);
207     set_menu_sensitivity("/Edit/Copy", FALSE);
208     set_menu_sensitivity("/Edit/Paste", FALSE);
209     set_menus_for_captured_packets(FALSE);
210     set_menus_for_selected_packet(FALSE);
211   }
212 }
213
214 void
215 set_menu_sensitivity_meat(GtkItemFactory *ifactory, gchar *path, gint val) {
216         GtkWidget *menu = NULL;
217         
218         if((menu = gtk_item_factory_get_widget(ifactory, path)) != NULL) {
219                 gtk_widget_set_sensitive(menu,val);
220         }
221 }
222
223 static void
224 set_menu_sensitivity (gchar *path, gint val) {
225   GSList *menu_list = popup_menu_list;
226   gchar *shortpath = strrchr(path, '/');
227
228   set_menu_sensitivity_meat(factory, path, val);
229
230   while (menu_list != NULL) {
231         set_menu_sensitivity_meat(menu_list->data, shortpath, val);
232         menu_list = g_slist_next(menu_list);
233   }
234   
235 }
236
237 void
238 set_menu_object_data_meat(GtkItemFactory *ifactory, gchar *path, gchar *key, gpointer data)
239 {
240         GtkWidget *menu = NULL;
241         
242         if ((menu = gtk_item_factory_get_widget(ifactory, path)) != NULL)
243                 gtk_object_set_data(GTK_OBJECT(menu), key, data);
244 }
245
246 void
247 set_menu_object_data (gchar *path, gchar *key, gpointer data) {
248   GSList *menu_list = popup_menu_list;
249   gchar *shortpath = strrchr(path, '/');
250   
251   set_menu_object_data_meat(factory, path, key, data);
252   while (menu_list != NULL) {
253         set_menu_object_data_meat(menu_list->data, shortpath, key, data);
254         menu_list = g_slist_next(menu_list);
255   }
256 }
257
258 void
259 popup_menu_handler(GtkWidget *widget, GdkEvent *event)
260 {
261         GtkWidget *menu = NULL;
262         GdkEventButton *event_button = NULL;
263
264         if(widget == NULL || event == NULL) {
265                 return;
266         }
267         
268         menu = widget;
269         if(event->type == GDK_BUTTON_PRESS) {
270                 event_button = (GdkEventButton *) event;
271                 
272                 if(event_button->button == 3) {
273                         gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, event_button->button, event_button->time);
274                 }
275         }
276 }
277
278 /* Enable or disable menu items based on whether you have a capture file
279    you've finished reading. */
280 void
281 set_menus_for_capture_file(gboolean have_capture_file)
282 {
283   set_menu_sensitivity("/File/Open...", have_capture_file);
284   set_menu_sensitivity("/File/Save As...", have_capture_file);
285   set_menu_sensitivity("/File/Close", have_capture_file);
286   set_menu_sensitivity("/File/Reload", have_capture_file);
287 }
288
289 /* Enable or disable menu items based on whether you have an unsaved
290    capture file you've finished reading. */
291 void
292 set_menus_for_unsaved_capture_file(gboolean have_unsaved_capture_file)
293 {
294   set_menu_sensitivity("/File/Save", have_unsaved_capture_file);
295 }
296
297 /* Enable or disable menu items based on whether there's a capture in
298    progress. */
299 void
300 set_menus_for_capture_in_progress(gboolean capture_in_progress)
301 {
302   set_menu_sensitivity("/File/Open...", !capture_in_progress);
303   set_menu_sensitivity("/Capture/Start...", !capture_in_progress);
304 }
305
306 /* Enable or disable menu items based on whether you have some captured
307    packets. */
308 void
309 set_menus_for_captured_packets(gboolean have_captured_packets)
310 {
311   set_menu_sensitivity("/File/Print...", have_captured_packets);
312   set_menu_sensitivity("/Edit/Find Frame...", have_captured_packets);
313   set_menu_sensitivity("/Edit/Go To Frame...", have_captured_packets);
314   set_menu_sensitivity("/Display/Match Selected", have_captured_packets);
315   set_menu_sensitivity("/Display/Colorize Display...", have_captured_packets);
316   set_menu_sensitivity("/Display/Find Frame...", have_captured_packets);
317   set_menu_sensitivity("/Display/Go To Frame...", have_captured_packets);
318   set_menu_sensitivity("/Tools/Summary", have_captured_packets);
319 }
320
321 /* Enable or disable menu items based on whether a packet is selected. */
322 void
323 set_menus_for_selected_packet(gboolean have_selected_packet)
324 {
325   set_menu_sensitivity("/File/Print Packet", have_selected_packet);
326   set_menu_sensitivity("/Display/Collapse All", have_selected_packet);
327   set_menu_sensitivity("/Display/Expand All", have_selected_packet);
328   set_menu_sensitivity("/Tools/Follow TCP Stream",
329       have_selected_packet ? (pi.ipproto == 6) : FALSE);
330 }