3 * $Id: proto_dlg.c,v 1.8 2001/03/01 21:34:09 gram Exp $
5 * Laurent Deniel <deniel@worldnet.fr>
7 * Ethereal - Network traffic analyzer
8 * By Gerald Combs <gerald@zing.org>
9 * Copyright 2000 Gerald Combs
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.
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.
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.
36 #ifdef HAVE_SYS_TYPES_H
37 #include <sys/types.h>
42 #include "gtkglobals.h"
46 #include "dlg_utils.h"
47 #include "proto_dlg.h"
49 static gboolean proto_delete_cb(GtkWidget *, gpointer);
50 static void proto_ok_cb(GtkWidget *, gpointer);
51 static void proto_apply_cb(GtkWidget *, gpointer);
52 static void proto_cancel_cb(GtkWidget *, gpointer);
53 static void proto_destroy_cb(GtkWidget *, gpointer);
55 static void show_proto_selection(GtkWidget *main, GtkWidget *container);
56 static gboolean set_proto_selection(GtkWidget *);
57 static gboolean revert_proto_selection(void);
59 static void toggle_all_cb(GtkWidget *button, gpointer parent_w);
60 static void enable_all_cb(GtkWidget *button, gpointer parent_w);
61 static void disable_all_cb(GtkWidget *button, gpointer parent_w);
63 static GtkWidget *proto_w = NULL;
65 /* list of protocols */
66 static GSList *protocol_list = NULL;
68 typedef struct protocol_data {
75 void proto_cb(GtkWidget *w, gpointer data)
78 GtkWidget *main_vb, *bbox, *proto_nb, *apply_bt, *cancel_bt, *ok_bt,
79 *label, *scrolled_w, *selection_vb, *button;
81 if (proto_w != NULL) {
82 reactivate_window(proto_w);
86 proto_w = dlg_window_new("Ethereal: Protocol");
87 gtk_signal_connect(GTK_OBJECT(proto_w), "delete_event",
88 GTK_SIGNAL_FUNC(proto_delete_cb), NULL);
89 gtk_signal_connect(GTK_OBJECT(proto_w), "destroy",
90 GTK_SIGNAL_FUNC(proto_destroy_cb), NULL);
91 gtk_widget_set_usize(GTK_WIDGET(proto_w), DEF_WIDTH * 2/3, DEF_HEIGHT * 2/3);
93 /* Container for each row of widgets */
95 main_vb = gtk_vbox_new(FALSE, 0);
96 gtk_container_border_width(GTK_CONTAINER(main_vb), 1);
97 gtk_container_add(GTK_CONTAINER(proto_w), main_vb);
98 gtk_widget_show(main_vb);
100 /* Protocol topics container */
102 proto_nb = gtk_notebook_new();
103 gtk_container_add(GTK_CONTAINER(main_vb), proto_nb);
104 /* XXX do not know why I need this to fill all space around buttons */
105 gtk_widget_set_usize(GTK_WIDGET(proto_nb), DEF_WIDTH * 2/3 - 50,
106 DEF_HEIGHT * 2/3 - 50);
108 /* Protocol selection panel ("enable/disable" protocols) */
110 selection_vb = gtk_vbox_new(FALSE, 0);
111 gtk_container_border_width(GTK_CONTAINER(selection_vb), 1);
112 label = gtk_label_new("Button pressed: protocol decoding is enabled");
113 gtk_widget_show(label);
114 gtk_box_pack_start(GTK_BOX(selection_vb), label, FALSE, FALSE, 0);
115 scrolled_w = gtk_scrolled_window_new(NULL, NULL);
116 gtk_container_set_border_width(GTK_CONTAINER(scrolled_w), 1);
117 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_w),
118 GTK_POLICY_AUTOMATIC,
120 set_scrollbar_placement_scrollw(scrolled_w, prefs.gui_scrollbar_on_right);
121 remember_scrolled_window(scrolled_w);
122 gtk_box_pack_start(GTK_BOX(selection_vb), scrolled_w, TRUE, TRUE, 0);
123 show_proto_selection(proto_w, scrolled_w);
124 gtk_widget_show(scrolled_w);
125 gtk_widget_show(selection_vb);
126 label = gtk_label_new("Decoding");
127 gtk_notebook_append_page(GTK_NOTEBOOK(proto_nb), selection_vb, label);
128 label = gtk_label_new("Note that when a protocol is disabled, "
129 "all linked sub-protocols are as well");
130 gtk_widget_show(label);
131 gtk_box_pack_start(GTK_BOX(selection_vb), label, FALSE, FALSE, 0);
134 bbox = gtk_hbutton_box_new();
135 gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_END);
136 gtk_button_box_set_spacing(GTK_BUTTON_BOX(bbox), 5);
137 gtk_box_pack_start(GTK_BOX(selection_vb), bbox, FALSE, FALSE, 0);
138 gtk_widget_show(bbox);
141 button = gtk_button_new_with_label("Toggle All");
142 gtk_signal_connect(GTK_OBJECT(button), "clicked",
143 GTK_SIGNAL_FUNC(toggle_all_cb), GTK_OBJECT(proto_w));
144 gtk_box_pack_start(GTK_BOX(bbox), button, TRUE, TRUE, 0);
145 gtk_widget_show(button);
148 button = gtk_button_new_with_label("Enable All");
149 gtk_signal_connect(GTK_OBJECT(button), "clicked",
150 GTK_SIGNAL_FUNC(enable_all_cb), GTK_OBJECT(proto_w));
151 gtk_box_pack_start(GTK_BOX(bbox), button, TRUE, TRUE, 0);
152 gtk_widget_show(button);
155 button = gtk_button_new_with_label("Disable All");
156 gtk_signal_connect(GTK_OBJECT(button), "clicked",
157 GTK_SIGNAL_FUNC(disable_all_cb), GTK_OBJECT(proto_w));
158 gtk_box_pack_start(GTK_BOX(bbox), button, TRUE, TRUE, 0);
159 gtk_widget_show(button);
162 /* XXX add other protocol-related panels here ... */
164 gtk_widget_show(proto_nb);
166 /* Ok, Apply, Cancel Buttons */
168 bbox = gtk_hbutton_box_new();
169 gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_END);
170 gtk_button_box_set_spacing(GTK_BUTTON_BOX(bbox), 5);
171 gtk_container_add(GTK_CONTAINER(main_vb), bbox);
172 gtk_widget_show(bbox);
174 ok_bt = gtk_button_new_with_label ("OK");
175 gtk_signal_connect(GTK_OBJECT(ok_bt), "clicked",
176 GTK_SIGNAL_FUNC(proto_ok_cb), GTK_OBJECT(proto_w));
177 GTK_WIDGET_SET_FLAGS(ok_bt, GTK_CAN_DEFAULT);
178 gtk_box_pack_start(GTK_BOX (bbox), ok_bt, TRUE, TRUE, 0);
179 gtk_widget_grab_default(ok_bt);
180 gtk_widget_show(ok_bt);
182 apply_bt = gtk_button_new_with_label ("Apply");
183 gtk_signal_connect(GTK_OBJECT(apply_bt), "clicked",
184 GTK_SIGNAL_FUNC(proto_apply_cb), GTK_OBJECT(proto_w));
185 GTK_WIDGET_SET_FLAGS(apply_bt, GTK_CAN_DEFAULT);
186 gtk_box_pack_start(GTK_BOX (bbox), apply_bt, TRUE, TRUE, 0);
187 gtk_widget_show(apply_bt);
189 cancel_bt = gtk_button_new_with_label ("Cancel");
190 gtk_signal_connect(GTK_OBJECT(cancel_bt), "clicked",
191 GTK_SIGNAL_FUNC(proto_cancel_cb), GTK_OBJECT(proto_w));
192 GTK_WIDGET_SET_FLAGS(cancel_bt, GTK_CAN_DEFAULT);
193 gtk_box_pack_start(GTK_BOX (bbox), cancel_bt, TRUE, TRUE, 0);
194 gtk_widget_show(cancel_bt);
196 dlg_set_cancel(proto_w, cancel_bt);
198 gtk_quit_add_destroy(gtk_main_level(), GTK_OBJECT(proto_w));
199 gtk_widget_show(proto_w);
206 toggle_all_cb(GtkWidget *button, gpointer parent_w)
211 for (entry = protocol_list; entry != NULL; entry = g_slist_next(entry)) {
213 protocol_data_t *p = entry->data;
215 button = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w),
217 /* gtk_toggle_button_toggled() didn't work for me... */
218 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button),
219 !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button)));
223 /* Enable/Disable All Helper */
225 set_active_all(GtkWidget *button, gpointer parent_w, gboolean new_state)
230 for (entry = protocol_list; entry != NULL; entry = g_slist_next(entry)) {
232 protocol_data_t *p = entry->data;
234 button = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w),
236 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), new_state);
242 enable_all_cb(GtkWidget *button, gpointer parent_w)
244 set_active_all(button, parent_w, TRUE);
249 disable_all_cb(GtkWidget *button, gpointer parent_w)
251 set_active_all(button, parent_w, FALSE);
254 static void proto_destroy_cb(GtkWidget *w, gpointer data)
259 gtk_widget_destroy(proto_w);
262 /* remove protocol list */
264 for (entry = protocol_list; entry != NULL; entry = g_slist_next(entry)) {
267 g_slist_free(protocol_list);
268 protocol_list = NULL;
272 /* Treat this as a cancel, by calling "proto_cancel_cb()".
273 XXX - that'll destroy the Protocols dialog; will that upset
274 a higher-level handler that says "OK, we've been asked to delete
275 this, so destroy it"? */
276 static gboolean proto_delete_cb(GtkWidget *proto_w, gpointer dummy)
278 proto_cancel_cb(NULL, proto_w);
282 static void proto_ok_cb(GtkWidget *ok_bt, gpointer parent_w)
286 redissect = set_proto_selection(GTK_WIDGET(parent_w));
287 gtk_widget_destroy(GTK_WIDGET(parent_w));
289 redissect_packets(&cfile);
292 static void proto_apply_cb(GtkWidget *apply_bt, gpointer parent_w)
294 if (set_proto_selection(GTK_WIDGET(parent_w)))
295 redissect_packets(&cfile);
298 static void proto_cancel_cb(GtkWidget *cancel_bt, gpointer parent_w)
302 redissect = revert_proto_selection();
303 gtk_widget_destroy(GTK_WIDGET(parent_w));
305 redissect_packets(&cfile);
308 static gboolean set_proto_selection(GtkWidget *parent_w)
311 gboolean need_redissect = FALSE;
313 for (entry = protocol_list; entry != NULL; entry = g_slist_next(entry)) {
315 protocol_data_t *p = entry->data;
317 button = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w),
319 if (proto_is_protocol_enabled(p->hfinfo_index) != GTK_TOGGLE_BUTTON (button)->active) {
320 proto_set_decoding(p->hfinfo_index, GTK_TOGGLE_BUTTON (button)->active);
321 need_redissect = TRUE;
325 return need_redissect;
327 } /* set_proto_selection */
329 static gboolean revert_proto_selection(void)
332 gboolean need_redissect = FALSE;
335 * Undo all the changes we've made to protocol enable flags.
337 for (entry = protocol_list; entry != NULL; entry = g_slist_next(entry)) {
338 protocol_data_t *p = entry->data;
340 if (proto_is_protocol_enabled(p->hfinfo_index) != p->was_enabled) {
341 proto_set_decoding(p->hfinfo_index, p->was_enabled);
342 need_redissect = TRUE;
346 return need_redissect;
348 } /* revert_proto_selection */
350 gint protocol_data_compare(gconstpointer a, gconstpointer b)
352 return strcmp(((protocol_data_t *)a)->abbrev,
353 ((protocol_data_t *)b)->abbrev);
356 static void show_proto_selection(GtkWidget *main, GtkWidget *container)
362 GtkTooltips *tooltips;
364 int i, t = 0, l = 0, nb_line, nb_proto = 0;
368 /* Iterate over all the protocols */
370 for (i = proto_get_first_protocol(&cookie); i != -1;
371 i = proto_get_next_protocol(&cookie)) {
372 if (proto_can_disable_protocol(i)) {
373 p = g_malloc(sizeof(protocol_data_t));
374 p->name = proto_get_protocol_name(i);
375 p->abbrev = proto_get_protocol_filter_name(i);
377 p->was_enabled = proto_is_protocol_enabled(i);
378 protocol_list = g_slist_insert_sorted(protocol_list,
379 p, protocol_data_compare);
384 /* create a table (n x NB_COL) of buttons */
386 nb_line = (nb_proto % NB_COL) ? nb_proto / NB_COL + 1 : nb_proto / NB_COL;
387 table = gtk_table_new (nb_line, NB_COL, FALSE);
388 gtk_table_set_row_spacings(GTK_TABLE (table), 1);
389 gtk_table_set_col_spacings(GTK_TABLE (table), 1);
390 gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(container), table);
391 gtk_widget_show(table);
393 tooltips = gtk_tooltips_new();
397 for (entry = protocol_list; entry != NULL; entry = g_slist_next(entry)) {
401 /* button label is the protocol abbrev */
402 button = gtk_toggle_button_new_with_label(p->abbrev);
403 /* tip is the complete protocol name */
404 gtk_tooltips_set_tip(tooltips, button, p->name, NULL);
405 gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(button),
406 proto_is_protocol_enabled(p->hfinfo_index));
407 gtk_object_set_data(GTK_OBJECT(main), p->abbrev, button);
408 gtk_table_attach_defaults (GTK_TABLE (table), button, l, l+1, t, t+1);
409 gtk_widget_show (button);
410 if (++nb_proto % NB_COL) {
419 } /* show_proto_selection */