This patch makes it possible to disable individual coloring rules
[obnox/wireshark/wip.git] / gtk / toolbar.c
1 /* toolbar.c
2  * The main toolbar
3  * Copyright 2003, Ulf Lamping <ulf.lamping@web.de>
4  *
5  * $Id$
6  *
7  * Wireshark - Network traffic analyzer
8  * By Gerald Combs <gerald@wireshark.org>
9  * Copyright 1998 Gerald Combs
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 /*
27  * This file implements a "main" toolbar for Wireshark (suitable for gtk1 and
28  * gtk2).
29  *
30  * As it is desirable to have the same toolbar implementation for gtk1 and gtk2 
31  * in Wireshark, only those library calls available in the gtk1 libraries 
32  * are used inside this file.
33  *
34  * Hint: gtk2 in comparison to gtk1 has a better way to handle with "common"
35  * icons; gtk2 calls this kind of icons "stock-icons"
36  * (stock-icons including: icons for "open", "save", "print", ...).
37  * The gtk2 version of this code uses them.
38  */
39
40 #ifdef HAVE_CONFIG_H
41 #include "config.h"
42 #endif
43
44 #include <gtk/gtk.h>
45
46 #ifdef HAVE_LIBPCAP
47 #include "capture_dlg.h"
48 #endif /* HAVE_LIBPCAP */
49 #include "filter_dlg.h"
50 #include "capture_file_dlg.h"
51 #include "find_dlg.h"
52 #include "goto_dlg.h"
53 #include "color.h"
54 #include "color_dlg.h"
55 #include <epan/prefs.h>
56 #include "prefs_dlg.h"
57 #include "main.h"
58 #include "help_dlg.h"
59 #include "gtkglobals.h"
60 #include "toolbar.h"
61 #include "keys.h"
62 #include "compat_macros.h"
63 #include "recent.h"
64 #include "packet_history.h"
65 #include "packet_list.h"
66 #include "color_filters.h"
67 #include "menu.h"
68
69 /* Most of the icons used here are coming (or are derived) from GTK2 stock icons.
70  * They were converted using "The Gimp" with standard conversion from png to xpm.
71  * All stock icons can be (currently) found at: 
72  * "ftp://ftp.gtk.org/pub/gtk/v2.0/gtk+-2.0.6.tar.bz2"
73  * in the directory "gtk+-2.0.6\gtk\stock-icons" */
74
75 /* The base for the new capture icons were GNOME system tools: Connection-Ethernet.png 
76  * see http://cvs.gnome.org/viewcvs/gnome-system-tools/pixmaps/ and it's 16x16 counterpart, 
77  * which are released under the GPL (or LGPL?). These icons were 
78  * merged together with some icons of the tremendous ximian icon collection (>1200!)
79  * for  OpenOffice? (LGPL'ed), which can be found at:
80  * http://www.novell.com/coolsolutions/feature/1637.html
81  */
82
83 #if GTK_MAJOR_VERSION < 2
84 #include "../image/toolbar/stock_save_as_24.xpm"
85 #include "../image/toolbar/stock_close_24.xpm"
86 #include "../image/toolbar/stock_refresh_24.xpm"
87 #include "../image/toolbar/stock_print_24.xpm"
88 #include "../image/toolbar/stock_search_24.xpm"
89 #include "../image/toolbar/stock_left_arrow_24.xpm"
90 #include "../image/toolbar/stock_right_arrow_24.xpm"
91 #include "../image/toolbar/stock_jump_to_24.xpm"
92 #include "../image/toolbar/stock_top_24.xpm"
93 #include "../image/toolbar/stock_bottom_24.xpm"
94 #include "../image/toolbar/stock_zoom_in_24.xpm"
95 #include "../image/toolbar/stock_zoom_out_24.xpm"
96 #include "../image/toolbar/stock_zoom_1_24.xpm"
97 #include "../image/toolbar/stock_colorselector_24.xpm"
98 #include "../image/toolbar/stock_help_24.xpm"
99 #endif /* GTK_MAJOR_VERSION */
100
101 /* these icons are derived from the original stock icons */
102 #ifdef HAVE_LIBPCAP
103 #include "../image/toolbar/capture_interfaces_24.xpm"
104 #include "../image/toolbar/capture_options_24.xpm"
105 #include "../image/toolbar/capture_start_24.xpm"
106 #include "../image/toolbar/capture_stop_24.xpm"
107 #include "../image/toolbar/capture_restart_24.xpm"
108 #include "../image/toolbar/capture_filter_24.xpm"
109 #if GTK_MAJOR_VERSION >= 2
110 #include "../image/toolbar/capture_details_24.xpm"
111 #endif
112 #endif /* HAVE_LIBPCAP */
113 #include "../image/toolbar/display_filter_24.xpm"
114 /* these icons are standard stock icons, but used for Wireshark specific stock icon labels */
115 #if GTK_MAJOR_VERSION >= 2
116 #include "../image/toolbar/stock_add_24.xpm"
117 #endif
118 #include "../image/toolbar/stock_open_24.xpm"
119 #if GTK_MAJOR_VERSION >= 2
120 #include "../image/toolbar/stock_ok_20.xpm"
121 #endif
122 #include "../image/toolbar/stock_save_24.xpm"
123 #include "../image/toolbar/stock_preferences_24.xpm"
124 #if GTK_MAJOR_VERSION >= 2
125 #include "../image/toolbar/stock_properties_24.xpm"
126 #include "../image/wsicon16.xpm"
127 #endif
128 #include "../image/toolbar/colorize_24.xpm"
129 #include "../image/toolbar/autoscroll_24.xpm"
130 #include "../image/toolbar/resize_columns_24.xpm"
131 #if GTK_MAJOR_VERSION >= 2
132 #include "../image/toolbar/time_24.xpm"
133 #include "../image/toolbar/internet_24.xpm"
134 #include "../image/toolbar/web_support_24.xpm"
135 #include "../image/toolbar/wiki_24.xpm"
136 #include "../image/toolbar/conversations_16.xpm"
137 #include "../image/toolbar/endpoints_16.xpm"
138 #include "../image/toolbar/graphs_16.xpm"
139 #include "../image/toolbar/telephony_16.xpm"
140 #include "../image/toolbar/decode_as_16.xpm"
141 #include "../image/toolbar/checkbox_16.xpm"
142 #include "../image/toolbar/file_set_list_16.xpm"
143 #include "../image/toolbar/file_set_next_16.xpm"
144 #include "../image/toolbar/file_set_previous_16.xpm"
145 #include "../image/toolbar/stock_close_24.xpm"
146 #endif
147
148
149 /* XXX: add this key to some .h file, as it adds a key to the top level Widget? */
150 #define E_TB_MAIN_KEY             "toolbar_main"
151
152
153 static gboolean toolbar_init = FALSE;
154
155 #if GTK_CHECK_VERSION(2,4,0)
156 #define BUTTON_TYPE GtkToolItem
157 #else /* GTK_CHECK_VERSION(2,4,0) */
158 #define BUTTON_TYPE GtkWidget
159 #endif /* GTK_CHECK_VERSION(2,4,0) */
160
161 #ifdef HAVE_LIBPCAP
162 static BUTTON_TYPE *capture_options_button, *new_button, *stop_button, *clear_button, *if_button;
163 static BUTTON_TYPE *capture_filter_button, *autoscroll_button;
164 #endif /* HAVE_LIBPCAP */
165 static BUTTON_TYPE *open_button, *save_button, *save_as_button, *close_button, *reload_button;
166 static BUTTON_TYPE *print_button, *find_button, *history_forward_button, *history_back_button;
167 static BUTTON_TYPE *go_to_button, *go_to_top_button, *go_to_bottom_button;
168 static BUTTON_TYPE *display_filter_button;
169 static BUTTON_TYPE *zoom_in_button, *zoom_out_button, *zoom_100_button, *colorize_button, *resize_columns_button;
170 static BUTTON_TYPE *color_display_button, *prefs_button, *help_button;
171
172 #if GTK_MAJOR_VERSION >= 2
173 typedef struct stock_pixmap_tag{
174     const char *    name;
175     const char **   xpm_data;
176 } stock_pixmap_t;
177
178 /* generate application specific stock items */
179 static void wireshark_stock_icons(void) {
180     GtkIconFactory * factory;
181     gint32 i;
182
183
184     /* register non-standard pixmaps with the gtk-stock engine */
185     static const GtkStockItem stock_items[] = {
186 #ifdef HAVE_LIBPCAP
187         { WIRESHARK_STOCK_CAPTURE_INTERFACES,    WIRESHARK_STOCK_LABEL_CAPTURE_INTERFACES,    0, 0, NULL },
188         { WIRESHARK_STOCK_CAPTURE_OPTIONS,       WIRESHARK_STOCK_LABEL_CAPTURE_OPTIONS,       0, 0, NULL },
189         { WIRESHARK_STOCK_CAPTURE_START,         WIRESHARK_STOCK_LABEL_CAPTURE_START,         0, 0, NULL },
190         { WIRESHARK_STOCK_CAPTURE_STOP,          WIRESHARK_STOCK_LABEL_CAPTURE_STOP,          0, 0, NULL },
191         { WIRESHARK_STOCK_CAPTURE_RESTART,       WIRESHARK_STOCK_LABEL_CAPTURE_RESTART,       0, 0, NULL },
192         { WIRESHARK_STOCK_CAPTURE_FILTER,        WIRESHARK_STOCK_LABEL_CAPTURE_FILTER,        0, 0, NULL },
193         { WIRESHARK_STOCK_CAPTURE_FILTER_ENTRY,  WIRESHARK_STOCK_LABEL_CAPTURE_FILTER_ENTRY,  0, 0, NULL },
194         { WIRESHARK_STOCK_CAPTURE_DETAILS,       WIRESHARK_STOCK_LABEL_CAPTURE_DETAILS,       0, 0, NULL },
195 #endif
196         { WIRESHARK_STOCK_DISPLAY_FILTER,        WIRESHARK_STOCK_LABEL_DISPLAY_FILTER,        0, 0, NULL },
197         { WIRESHARK_STOCK_DISPLAY_FILTER_ENTRY,  WIRESHARK_STOCK_LABEL_DISPLAY_FILTER_ENTRY,  0, 0, NULL },
198         { WIRESHARK_STOCK_PREFS,                 WIRESHARK_STOCK_LABEL_PREFS,                 0, 0, NULL },
199         { WIRESHARK_STOCK_BROWSE,                WIRESHARK_STOCK_LABEL_BROWSE,                0, 0, NULL },
200         { WIRESHARK_STOCK_CREATE_STAT,           WIRESHARK_STOCK_LABEL_CREATE_STAT,           0, 0, NULL },
201         { WIRESHARK_STOCK_EXPORT,                WIRESHARK_STOCK_LABEL_EXPORT,                0, 0, NULL },
202         { WIRESHARK_STOCK_IMPORT,                WIRESHARK_STOCK_LABEL_IMPORT,                0, 0, NULL },
203         { WIRESHARK_STOCK_EDIT,                  WIRESHARK_STOCK_LABEL_EDIT,                  0, 0, NULL },
204         { WIRESHARK_STOCK_ADD_EXPRESSION,        WIRESHARK_STOCK_LABEL_ADD_EXPRESSION,        0, 0, NULL },
205         { WIRESHARK_STOCK_DONT_SAVE,             WIRESHARK_STOCK_LABEL_DONT_SAVE,             0, 0, NULL },
206         { WIRESHARK_STOCK_ABOUT,                 WIRESHARK_STOCK_LABEL_ABOUT,                 0, 0, NULL },
207         { WIRESHARK_STOCK_COLORIZE,              WIRESHARK_STOCK_LABEL_COLORIZE,              0, 0, NULL },
208         { WIRESHARK_STOCK_AUTOSCROLL,            WIRESHARK_STOCK_LABEL_AUTOSCROLL,            0, 0, NULL },
209         { WIRESHARK_STOCK_RESIZE_COLUMNS,        WIRESHARK_STOCK_LABEL_RESIZE_COLUMNS,        0, 0, NULL },
210         { WIRESHARK_STOCK_TIME,                  WIRESHARK_STOCK_LABEL_TIME,                  0, 0, NULL },
211         { WIRESHARK_STOCK_INTERNET,              WIRESHARK_STOCK_LABEL_INTERNET,              0, 0, NULL },
212         { WIRESHARK_STOCK_WEB_SUPPORT,           WIRESHARK_STOCK_LABEL_WEB_SUPPORT,           0, 0, NULL },
213         { WIRESHARK_STOCK_WIKI,                  WIRESHARK_STOCK_LABEL_WIKI,                  0, 0, NULL },
214         { WIRESHARK_STOCK_CONVERSATIONS,         WIRESHARK_STOCK_LABEL_CONVERSATIONS,         0, 0, NULL },
215         { WIRESHARK_STOCK_ENDPOINTS,             WIRESHARK_STOCK_LABEL_ENDPOINTS,             0, 0, NULL },
216         { WIRESHARK_STOCK_GRAPHS,                WIRESHARK_STOCK_LABEL_GRAPHS,                0, 0, NULL },
217         { WIRESHARK_STOCK_TELEPHONY,             WIRESHARK_STOCK_LABEL_TELEPHONY,             0, 0, NULL },
218         { WIRESHARK_STOCK_DECODE_AS,             WIRESHARK_STOCK_LABEL_DECODE_AS,             0, 0, NULL },
219         { WIRESHARK_STOCK_CHECKBOX,              WIRESHARK_STOCK_LABEL_CHECKBOX,              0, 0, NULL },
220         { WIRESHARK_STOCK_FILE_SET_LIST,         WIRESHARK_STOCK_LABEL_FILE_SET_LIST,         0, 0, NULL },
221         { WIRESHARK_STOCK_FILE_SET_NEXT,         WIRESHARK_STOCK_LABEL_FILE_SET_NEXT,         0, 0, NULL },
222         { WIRESHARK_STOCK_FILE_SET_PREVIOUS,     WIRESHARK_STOCK_LABEL_FILE_SET_PREVIOUS,     0, 0, NULL },
223         { WIRESHARK_STOCK_FILTER_OUT_STREAM,     WIRESHARK_STOCK_LABEL_FILTER_OUT_STREAM,     0, 0, NULL },
224         { WIRESHARK_STOCK_ENABLE,                WIRESHARK_STOCK_LABEL_ENABLE,                0, 0, NULL },
225         { WIRESHARK_STOCK_DISABLE,               WIRESHARK_STOCK_LABEL_DISABLE,               0, 0, NULL }
226     };
227
228     static const stock_pixmap_t pixmaps[] = {
229 #ifdef HAVE_LIBPCAP
230         { WIRESHARK_STOCK_CAPTURE_INTERFACES,    capture_interfaces_24_xpm },
231         { WIRESHARK_STOCK_CAPTURE_OPTIONS,       capture_options_24_xpm },
232         { WIRESHARK_STOCK_CAPTURE_START,         capture_start_24_xpm },
233         { WIRESHARK_STOCK_CAPTURE_STOP,          capture_stop_24_xpm },
234         { WIRESHARK_STOCK_CAPTURE_RESTART,       capture_restart_24_xpm },
235         { WIRESHARK_STOCK_CAPTURE_FILTER,        capture_filter_24_xpm },
236         { WIRESHARK_STOCK_CAPTURE_FILTER_ENTRY,  capture_filter_24_xpm },
237         { WIRESHARK_STOCK_CAPTURE_DETAILS,       capture_details_24_xpm },
238 #endif
239         { WIRESHARK_STOCK_DISPLAY_FILTER,        display_filter_24_xpm },
240         { WIRESHARK_STOCK_DISPLAY_FILTER_ENTRY,  display_filter_24_xpm },
241         { WIRESHARK_STOCK_PREFS,                 stock_preferences_24_xpm },
242         { WIRESHARK_STOCK_BROWSE,                stock_open_24_xpm },
243         { WIRESHARK_STOCK_CREATE_STAT,           stock_ok_20_xpm },
244         { WIRESHARK_STOCK_EXPORT,                stock_save_24_xpm },    /* XXX: needs a better icon */
245         { WIRESHARK_STOCK_IMPORT,                stock_save_24_xpm },    /* XXX: needs a better icon */
246         { WIRESHARK_STOCK_EDIT,                  stock_properties_24_xpm },
247         { WIRESHARK_STOCK_ADD_EXPRESSION,        stock_add_24_xpm },
248         { WIRESHARK_STOCK_ABOUT,                 wsicon16_xpm },
249         { WIRESHARK_STOCK_COLORIZE,              colorize_24_xpm },
250         { WIRESHARK_STOCK_AUTOSCROLL,            autoscroll_24_xpm },
251         { WIRESHARK_STOCK_RESIZE_COLUMNS,        resize_columns_24_xpm},
252         { WIRESHARK_STOCK_TIME,                  time_24_xpm},
253         { WIRESHARK_STOCK_INTERNET,              internet_24_xpm},
254         { WIRESHARK_STOCK_WEB_SUPPORT,           web_support_24_xpm},
255         { WIRESHARK_STOCK_WIKI,                  wiki_24_xpm},
256         { WIRESHARK_STOCK_CONVERSATIONS,         conversations_16_xpm},
257         { WIRESHARK_STOCK_ENDPOINTS,             endpoints_16_xpm},
258         { WIRESHARK_STOCK_GRAPHS,                graphs_16_xpm},
259         { WIRESHARK_STOCK_TELEPHONY,             telephony_16_xpm},
260         { WIRESHARK_STOCK_DECODE_AS,             decode_as_16_xpm},
261         { WIRESHARK_STOCK_CHECKBOX,              checkbox_16_xpm},
262         { WIRESHARK_STOCK_FILE_SET_LIST,         file_set_list_16_xpm},
263         { WIRESHARK_STOCK_FILE_SET_NEXT,         file_set_next_16_xpm},
264         { WIRESHARK_STOCK_FILE_SET_PREVIOUS,     file_set_previous_16_xpm},
265         { WIRESHARK_STOCK_FILTER_OUT_STREAM,     display_filter_24_xpm},
266         { WIRESHARK_STOCK_ENABLE,                checkbox_16_xpm},
267         { WIRESHARK_STOCK_DISABLE,               stock_close_24_xpm},
268         { NULL, NULL }
269     };
270
271     /* Register our stock items */
272     gtk_stock_add (stock_items, G_N_ELEMENTS (stock_items));
273
274     /* Add our custom icon factory to the list of defaults */
275     factory = gtk_icon_factory_new();
276     gtk_icon_factory_add_default(factory);
277
278     /* Create the stock items to add into our icon factory */
279     for (i = 0; pixmaps[i].name != NULL; i++) {
280         GdkPixbuf * pixbuf;
281         GtkIconSet *icon_set;
282
283         pixbuf = gdk_pixbuf_new_from_xpm_data((const char **) (pixmaps[i].xpm_data));
284         g_assert(pixbuf);
285         icon_set = gtk_icon_set_new_from_pixbuf (pixbuf);
286         gtk_icon_factory_add (factory, pixmaps[i].name, icon_set);
287         gtk_icon_set_unref (icon_set);
288         g_object_unref (G_OBJECT (pixbuf));
289     }
290
291     /* Drop our reference to the factory, GTK will hold a reference.*/
292     g_object_unref (G_OBJECT (factory));
293 }
294 #endif
295
296
297 /*
298  * Redraw all toolbars (currently only the main toolbar)
299  */
300 void
301 toolbar_redraw_all(void)
302 {
303     GtkWidget     *main_tb;
304
305     main_tb = OBJECT_GET_DATA(top_level, E_TB_MAIN_KEY);
306
307     gtk_toolbar_set_style(GTK_TOOLBAR(main_tb),
308                           prefs.gui_toolbar_main_style);
309
310 #if GTK_MAJOR_VERSION < 2
311     /* In GTK+ 1.2[.x], the toolbar takes the maximum vertical size it ever
312      * had, even if you change the style in such a way as to reduce its
313      * height, unless we queue a resize (which resizes ALL elements in the
314      * top-level container).
315      *
316      * In GTK+ 2.x, this isn't necessary - it does the right thing. */
317     gtk_container_queue_resize(GTK_CONTAINER(top_level));
318 #endif /* GTK_MAJOR_VERSION */
319 }
320
321 /* Enable or disable toolbar items based on whether you have a capture file
322    you've finished reading. */
323 void set_toolbar_for_capture_file(gboolean have_capture_file) {
324     if (toolbar_init) {
325         gtk_widget_set_sensitive(GTK_WIDGET(save_button), have_capture_file);
326         gtk_widget_set_sensitive(GTK_WIDGET(save_as_button), have_capture_file);
327         gtk_widget_set_sensitive(GTK_WIDGET(close_button), have_capture_file);
328         gtk_widget_set_sensitive(GTK_WIDGET(reload_button), have_capture_file);
329     }
330 }
331
332 /* Enable or disable menu items based on whether you have an unsaved
333    capture file you've finished reading. */
334 void set_toolbar_for_unsaved_capture_file(gboolean have_unsaved_capture_file) {
335     if (toolbar_init) {
336         if(have_unsaved_capture_file) {
337             gtk_widget_hide(GTK_WIDGET(save_as_button));
338             gtk_widget_show(GTK_WIDGET(save_button));
339         } else {
340             gtk_widget_show(GTK_WIDGET(save_as_button));
341             gtk_widget_hide(GTK_WIDGET(save_button));
342         }
343         /*gtk_widget_set_sensitive((GTK_WIDGET(save_button), have_unsaved_capture_file);
344         gtk_widget_set_sensitive(GTK_WIDGET(save_as_button), !have_unsaved_capture_file);*/
345     }
346 }
347
348
349 /** The packet history has changed, we need to update the menu.
350  *
351  * @param back_history some back history entries available
352  * @param forward_history some forward history entries available
353  */
354 void set_toolbar_for_packet_history(gboolean back_history, gboolean forward_history) {
355     gtk_widget_set_sensitive(GTK_WIDGET(history_back_button), back_history);
356     gtk_widget_set_sensitive(GTK_WIDGET(history_forward_button), forward_history);
357 }
358
359
360 /* XXX - this is a quick and dirty hack to get the current state of capturing.
361  * this has to be improved, and should be reside somewhere in the capture engine. */
362 gboolean g_is_capture_in_progress = FALSE;
363
364 gboolean
365 is_capture_in_progress(void)
366 {
367     return g_is_capture_in_progress;
368 }
369
370 /* set toolbar state "have a capture in progress" */
371 void set_toolbar_for_capture_in_progress(gboolean capture_in_progress) {
372
373     g_is_capture_in_progress = capture_in_progress;
374
375     if (toolbar_init) {
376 #ifdef HAVE_LIBPCAP
377         gtk_widget_set_sensitive(GTK_WIDGET(capture_options_button), !capture_in_progress);
378         gtk_widget_set_sensitive(GTK_WIDGET(new_button), !capture_in_progress);
379         gtk_widget_set_sensitive(GTK_WIDGET(stop_button), capture_in_progress);
380         gtk_widget_set_sensitive(GTK_WIDGET(clear_button), capture_in_progress);
381         /*if (capture_in_progress) {
382             gtk_widget_hide(GTK_WIDGET(new_button));
383             gtk_widget_show(GTK_WIDGET(stop_button));
384         } else {
385             gtk_widget_show(GTK_WIDGET(new_button));
386             gtk_widget_hide(GTK_WIDGET(stop_button));
387         }*/
388 #endif /* HAVE_LIBPCAP */
389         gtk_widget_set_sensitive(GTK_WIDGET(open_button), !capture_in_progress);
390     }
391 }
392
393 /* set toolbar state "have packets captured" */
394 void set_toolbar_for_captured_packets(gboolean have_captured_packets) {
395
396     if (toolbar_init) {
397         gtk_widget_set_sensitive(GTK_WIDGET(print_button),
398                                  have_captured_packets);
399         gtk_widget_set_sensitive(GTK_WIDGET(find_button),
400                                  have_captured_packets);
401         gtk_widget_set_sensitive(GTK_WIDGET(history_back_button),
402                                  have_captured_packets);
403         gtk_widget_set_sensitive(GTK_WIDGET(history_forward_button),
404                                  have_captured_packets);
405         gtk_widget_set_sensitive(GTK_WIDGET(go_to_button),
406                                  have_captured_packets);
407         gtk_widget_set_sensitive(GTK_WIDGET(go_to_top_button),
408                                  have_captured_packets);
409         gtk_widget_set_sensitive(GTK_WIDGET(go_to_bottom_button),
410                                  have_captured_packets);
411         gtk_widget_set_sensitive(GTK_WIDGET(zoom_in_button),
412                                  have_captured_packets);
413         gtk_widget_set_sensitive(GTK_WIDGET(zoom_out_button),
414                                  have_captured_packets);
415         gtk_widget_set_sensitive(GTK_WIDGET(zoom_100_button),
416                                  have_captured_packets);        
417         gtk_widget_set_sensitive(GTK_WIDGET(resize_columns_button),
418                                  have_captured_packets);
419         /* XXX - I don't see a reason why this should be done (as it is in the
420          * menus) */
421         /* gtk_widget_set_sensitive(GTK_WIDGET(color_display_button),
422            have_captured_packets);*/
423     }
424 }
425
426
427 /* helper function: add a separator to the toolbar */
428 static void toolbar_append_separator(GtkWidget *toolbar) {
429 #if GTK_MAJOR_VERSION < 2
430     /* the usage of a gtk_separator doesn't seem to work for a toolbar.
431      * (at least in the win32 port of gtk 1.3)
432      * So simply add a few spaces */
433     gtk_toolbar_append_space(GTK_TOOLBAR(toolbar)); /* space after item */
434     gtk_toolbar_append_space(GTK_TOOLBAR(toolbar)); /* space after item */
435 #else /* GTK_MAJOR_VERSION < 2 */
436 #if GTK_CHECK_VERSION(2,4,0)
437     GtkToolItem *tool_item = gtk_separator_tool_item_new();
438     gtk_toolbar_insert(GTK_TOOLBAR(toolbar), tool_item, -1);
439     gtk_widget_show(GTK_WIDGET(tool_item));
440 #else /* GTK_CHECK_VERSION(2,4,0) */
441     /* GTK 2 uses (as it should be) a seperator when adding this space */
442     gtk_toolbar_append_space(GTK_TOOLBAR(toolbar));
443 #endif /* GTK_CHECK_VERSION(2,4,0) */
444 #endif /* GTK_MAJOR_VERSION */
445 }
446
447
448
449 #if GTK_MAJOR_VERSION < 2
450 #define toolbar_item(new_item, window, toolbar, stock, tooltips, tooltip_text, xpm, callback, user_data) { \
451     icon = gdk_pixmap_create_from_xpm_d(window->window, &mask, &window->style->white, (gchar **) xpm); \
452     iconw = gtk_pixmap_new(icon, mask); \
453     new_item = gtk_toolbar_append_item(GTK_TOOLBAR (toolbar), \
454         stock, tooltip_text, "Private", iconw, GTK_SIGNAL_FUNC(callback), user_data);\
455     }
456 #else /* GTK_MAJOR_VERSION < 2 */
457 #if GTK_CHECK_VERSION(2,4,0)
458 #define toolbar_item(new_item, window, toolbar, stock, tooltips, tooltip_text, xpm, callback, user_data) { \
459     new_item = gtk_tool_button_new_from_stock(stock); \
460     gtk_tool_item_set_tooltip(new_item, tooltips,  tooltip_text, NULL); \
461     g_signal_connect(new_item, "clicked", G_CALLBACK(callback), user_data); \
462     gtk_toolbar_insert(GTK_TOOLBAR(toolbar), new_item, -1); \
463     gtk_widget_show(GTK_WIDGET(new_item)); \
464     }
465
466 #else /* GTK_CHECK_VERSION(2,4,0) */
467
468 #define toolbar_item(new_item, window, toolbar, stock, tooltips, tooltip_text, xpm, callback, user_data) { \
469     new_item = gtk_toolbar_insert_stock(GTK_TOOLBAR(toolbar), \
470         stock, tooltip_text, "Private", G_CALLBACK(callback), user_data, -1);\
471     }
472 #endif /* GTK_CHECK_VERSION(2,4,0) */
473 #endif /* GTK_MAJOR_VERSION */
474
475
476 #if GTK_MAJOR_VERSION < 2
477 #define toolbar_icon(new_icon, window, xpm) { \
478     icon = gdk_pixmap_create_from_xpm_d(window->window, &mask, &window->style->white, (gchar **) xpm); \
479     new_icon = gtk_pixmap_new(icon, mask); \
480     }
481 #else
482 #define toolbar_icon(new_icon, window, xpm) { \
483     icon = gdk_pixmap_create_from_xpm_d(window->window, &mask, &window->style->white, (gchar **) xpm); \
484     new_icon = gtk_image_new_from_pixmap(icon, mask); \
485     }
486 #endif
487
488
489 #if GTK_CHECK_VERSION(2,4,0)
490 #define toolbar_toggle_button(new_item, window, toolbar, stock, tooltips, tooltip_text, xpm, callback, user_data) { \
491     new_item = gtk_toggle_tool_button_new_from_stock(stock); \
492     gtk_tool_item_set_tooltip(new_item, tooltips,  tooltip_text, NULL); \
493     g_signal_connect(new_item, "toggled", G_CALLBACK(callback), user_data); \
494     gtk_toolbar_insert(GTK_TOOLBAR(toolbar), new_item, -1); \
495     gtk_widget_show_all(GTK_WIDGET(new_item)); \
496     }
497 #else /* GTK_CHECK_VERSION(2,4,0) */
498 #define toolbar_toggle_button(new_item, window, toolbar, stock, tooltips, tooltip_text, xpm, callback, user_data) { \
499     toolbar_icon(iconw, window, xpm); \
500     new_item = gtk_toolbar_append_element(GTK_TOOLBAR(toolbar), \
501         GTK_TOOLBAR_CHILD_TOGGLEBUTTON, NULL, \
502         stock, tooltip_text, "Private", iconw, GTK_SIGNAL_FUNC(callback), user_data);\
503     }
504 #endif /* GTK_CHECK_VERSION(2,4,0) */
505
506
507 static void
508 colorize_toggle_cb(GtkWidget *toggle_button, gpointer user_data _U_)  {
509 #if GTK_CHECK_VERSION(2,4,0)
510     menu_colorize_changed(gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(toggle_button)));
511 #else /* GTK_CHECK_VERSION(2,4,0) */
512     menu_colorize_changed(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(toggle_button)));
513 #endif /* GTK_CHECK_VERSION(2,4,0) */
514 }
515
516 void
517 toolbar_colorize_changed(gboolean packet_list_colorize) {
518 #if GTK_CHECK_VERSION(2,4,0)
519     if(gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(colorize_button)) != packet_list_colorize) {
520         gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(colorize_button), packet_list_colorize);
521     }
522 #else /* GTK_CHECK_VERSION(2,4,0) */
523     if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(colorize_button)) != packet_list_colorize) {
524         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(colorize_button), packet_list_colorize);
525     }
526 #endif /* GTK_CHECK_VERSION(2,4,0) */
527 }
528
529
530 #ifdef HAVE_LIBPCAP
531 static void
532 auto_scroll_live_toggle_cb(GtkWidget *autoscroll_button, gpointer user_data _U_) {
533 #if GTK_CHECK_VERSION(2,4,0)
534     menu_auto_scroll_live_changed(gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(autoscroll_button)));
535 #else /* GTK_CHECK_VERSION(2,4,0) */
536     menu_auto_scroll_live_changed(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(autoscroll_button)));
537
538 #endif /* GTK_CHECK_VERSION(2,4,0) */
539 }
540
541 void
542 toolbar_auto_scroll_live_changed(gboolean auto_scroll_live) {
543 #if GTK_CHECK_VERSION(2,4,0)
544     if(gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(autoscroll_button)) != auto_scroll_live) {
545         gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(autoscroll_button), auto_scroll_live);
546     }
547 #else /* GTK_CHECK_VERSION(2,4,0) */
548     if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(autoscroll_button)) != auto_scroll_live) {
549         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(autoscroll_button), auto_scroll_live);
550     }
551 #endif /* GTK_CHECK_VERSION(2,4,0) */
552 }
553 #endif
554
555 /*
556  * Create all toolbars (currently only the main toolbar)
557  */
558 GtkWidget *
559 toolbar_new(void)
560 {
561     GtkWidget *main_tb;
562     GtkWidget *window = top_level;
563 #if !GTK_CHECK_VERSION(2,4,0)
564     GdkPixmap *icon;
565     GdkBitmap * mask;
566     GtkWidget *iconw;
567 #endif
568     GtkTooltips *tooltips;
569
570     tooltips = gtk_tooltips_new();
571     
572 #if GTK_MAJOR_VERSION >= 2
573     /* create application specific stock icons */
574     wireshark_stock_icons();
575 #endif
576
577     /* this function should be only called once! */
578     g_assert(!toolbar_init);
579
580     /* we need to realize the window because we use pixmaps for 
581      * items on the toolbar in the context of it */
582     /* (coming from the gtk example, please don't ask me why ;-) */
583     gtk_widget_realize(window);
584
585     /* toolbar will be horizontal, with both icons and text (as default here) */
586     /* (this will usually be overwritten by the preferences setting) */
587 #if GTK_MAJOR_VERSION < 2
588     main_tb = gtk_toolbar_new(GTK_ORIENTATION_HORIZONTAL,
589                                GTK_TOOLBAR_BOTH);
590     gtk_toolbar_set_space_size(GTK_TOOLBAR(main_tb), 3);
591     /* the "space lines" in GTK1 looks ugly, so don't use them */
592     /* gtk_toolbar_set_space_style(GTK_TOOLBAR(main_tb), GTK_TOOLBAR_SPACE_LINE); */
593 #else
594     main_tb = gtk_toolbar_new();
595     gtk_toolbar_set_orientation(GTK_TOOLBAR(main_tb),
596                                 GTK_ORIENTATION_HORIZONTAL);
597 #endif /* GTK_MAJOR_VERSION */
598
599     OBJECT_SET_DATA(top_level, E_TB_MAIN_KEY, main_tb);
600
601
602 #ifdef HAVE_LIBPCAP
603     toolbar_item(if_button, window, main_tb, 
604         WIRESHARK_STOCK_CAPTURE_INTERFACES, tooltips, "List the available capture interfaces...", capture_interfaces_24_xpm, capture_if_cb, NULL);
605
606     toolbar_item(capture_options_button, window, main_tb, 
607         WIRESHARK_STOCK_CAPTURE_OPTIONS, tooltips, "Show the capture options...", capture_options_24_xpm, capture_prep_cb, NULL);
608
609     toolbar_item(new_button, window, main_tb, 
610         WIRESHARK_STOCK_CAPTURE_START, tooltips, "Start a new live capture", capture_start_24_xpm, capture_start_cb, NULL);
611
612     toolbar_item(stop_button, window, main_tb, 
613         WIRESHARK_STOCK_CAPTURE_STOP, tooltips, "Stop the running live capture", capture_stop_24_xpm, capture_stop_cb, NULL);
614
615     toolbar_item(clear_button, window, main_tb, 
616         WIRESHARK_STOCK_CAPTURE_RESTART, tooltips, "Restart the running live capture", capture_restart_24_xpm, capture_restart_cb, NULL);
617
618     toolbar_append_separator(main_tb);
619 #endif /* HAVE_LIBPCAP */
620
621     toolbar_item(open_button, window, main_tb, 
622         GTK_STOCK_OPEN, tooltips, "Open a capture file...", stock_open_24_xpm, file_open_cmd_cb, NULL);
623
624     toolbar_item(save_button, window, main_tb, 
625         GTK_STOCK_SAVE, tooltips, "Save this capture file...", stock_save_24_xpm, file_save_cmd_cb, NULL);
626
627     toolbar_item(save_as_button, window, main_tb, 
628         GTK_STOCK_SAVE_AS, tooltips, "Save this capture file as...", stock_save_as_24_xpm, file_save_as_cmd_cb, NULL);
629
630     toolbar_item(close_button, window, main_tb, 
631         GTK_STOCK_CLOSE, tooltips, "Close this capture file", stock_close_24_xpm, file_close_cmd_cb, NULL);
632
633     toolbar_item(reload_button, window, main_tb, 
634         GTK_STOCK_REFRESH, tooltips, "Reload this capture file", stock_refresh_24_xpm, file_reload_cmd_cb, NULL);
635
636     toolbar_item(print_button, window, main_tb, 
637         GTK_STOCK_PRINT, tooltips, "Print packet(s)...", stock_print_24_xpm, file_print_cmd_cb, NULL);
638
639     toolbar_append_separator(main_tb);
640
641     toolbar_item(find_button, window, main_tb, 
642         GTK_STOCK_FIND, tooltips, "Find a packet...", stock_search_24_xpm, find_frame_cb, NULL);
643
644     toolbar_item(history_back_button, window, main_tb, 
645         GTK_STOCK_GO_BACK, tooltips, "Go back in packet history", stock_left_arrow_24_xpm, history_back_cb, NULL);
646
647     toolbar_item(history_forward_button, window, main_tb, 
648         GTK_STOCK_GO_FORWARD, tooltips, "Go forward in packet history", stock_right_arrow_24_xpm, history_forward_cb, NULL);
649
650     toolbar_item(go_to_button, window, main_tb, 
651         GTK_STOCK_JUMP_TO, tooltips, "Go to the packet with number...", stock_jump_to_24_xpm, goto_frame_cb, NULL);
652
653     toolbar_item(go_to_top_button, window, main_tb, 
654         GTK_STOCK_GOTO_TOP, tooltips, "Go to the first packet", stock_top_24_xpm, goto_top_frame_cb, NULL);
655
656     toolbar_item(go_to_bottom_button, window, main_tb, 
657         GTK_STOCK_GOTO_BOTTOM, tooltips, "Go to the last packet", stock_bottom_24_xpm, goto_bottom_frame_cb, NULL);
658
659     toolbar_append_separator(main_tb);
660
661     toolbar_toggle_button(colorize_button, window, main_tb, 
662         WIRESHARK_STOCK_COLORIZE, tooltips, "Colorize Packet List", colorize_24_xpm, colorize_toggle_cb, NULL);
663
664 #ifdef HAVE_LIBPCAP
665     toolbar_toggle_button(autoscroll_button, window, main_tb, 
666         WIRESHARK_STOCK_AUTOSCROLL, tooltips, "Auto Scroll Packet List in Live Capture", autoscroll_24_xpm, auto_scroll_live_toggle_cb, NULL);
667 #endif
668
669     toolbar_append_separator(main_tb);
670
671     toolbar_item(zoom_in_button, window, main_tb, 
672         GTK_STOCK_ZOOM_IN, tooltips, "Zoom in", stock_zoom_in_24_xpm, view_zoom_in_cb, NULL);
673
674     toolbar_item(zoom_out_button, window, main_tb, 
675         GTK_STOCK_ZOOM_OUT, tooltips, "Zoom out", stock_zoom_out_24_xpm, view_zoom_out_cb, NULL);
676
677     toolbar_item(zoom_100_button, window, main_tb, 
678         GTK_STOCK_ZOOM_100, tooltips, "Zoom 100%", stock_zoom_1_24_xpm, view_zoom_100_cb, NULL);
679
680     toolbar_item(resize_columns_button, window, main_tb, 
681         WIRESHARK_STOCK_RESIZE_COLUMNS, tooltips, "Resize All Columns", resize_columns_24_xpm, packet_list_resize_columns_cb, NULL);
682
683     toolbar_append_separator(main_tb);
684     
685 #ifdef HAVE_LIBPCAP
686     toolbar_item(capture_filter_button, window, main_tb, 
687         WIRESHARK_STOCK_CAPTURE_FILTER, tooltips, "Edit capture filter...", capture_filter_24_xpm, cfilter_dialog_cb, NULL);
688 #endif /* HAVE_LIBPCAP */
689
690     toolbar_item(display_filter_button, window, main_tb, 
691         WIRESHARK_STOCK_DISPLAY_FILTER, tooltips, "Edit/apply display filter...", display_filter_24_xpm, dfilter_dialog_cb, NULL);
692
693     toolbar_item(color_display_button, window, main_tb, 
694         GTK_STOCK_SELECT_COLOR, tooltips, "Edit coloring rules...", stock_colorselector_24_xpm, color_display_cb, NULL);
695
696     /* the preference button uses it's own Stock icon label "Prefs", as "Preferences" is too long */
697     toolbar_item(prefs_button, window, main_tb, 
698         WIRESHARK_STOCK_PREFS, tooltips, "Edit preferences...", stock_preferences_24_xpm, prefs_cb, NULL);
699
700     toolbar_append_separator(main_tb);
701
702     toolbar_item(help_button, window, main_tb, 
703         GTK_STOCK_HELP, tooltips, "Show some help...", stock_help_24_xpm, topic_cb, GINT_TO_POINTER(HELP_CONTENT));
704
705     /* disable all "sensitive" items by default */
706     toolbar_init = TRUE;
707     set_toolbar_for_unsaved_capture_file(FALSE);
708     set_toolbar_for_captured_packets(FALSE);
709     set_toolbar_for_capture_file(FALSE);
710 #ifdef HAVE_LIBPCAP
711     set_toolbar_for_capture_in_progress(FALSE);
712 #endif /* HAVE_LIBPCAP */
713
714     /* make current preferences effective */
715     toolbar_redraw_all();
716
717     return main_tb;
718 }
719
720 void
721 set_toolbar_object_data(gchar *key, gpointer data)
722 {
723     OBJECT_SET_DATA(open_button, key, data);
724     OBJECT_SET_DATA(reload_button, key, data);
725 }