3 * $Id: proto_dlg.c,v 1.17 2002/11/11 15:39:06 oabad Exp $
5 * Laurent Deniel <deniel@worldnet.fr>
7 * Ethereal - Network traffic analyzer
8 * By Gerald Combs <gerald@ethereal.com>
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.
38 #include "dlg_utils.h"
39 #include "proto_dlg.h"
40 #include "compat_macros.h"
42 static gboolean proto_delete_cb(GtkWidget *, gpointer);
43 static void proto_ok_cb(GtkWidget *, gpointer);
44 static void proto_apply_cb(GtkWidget *, gpointer);
45 static void proto_cancel_cb(GtkWidget *, gpointer);
46 static void proto_destroy_cb(GtkWidget *, gpointer);
48 static void show_proto_selection(GtkWidget *main, GtkWidget *container);
49 static gboolean set_proto_selection(GtkWidget *);
50 static gboolean revert_proto_selection(void);
52 static void toggle_all_cb(GtkWidget *button, gpointer parent_w);
53 static void enable_all_cb(GtkWidget *button, gpointer parent_w);
54 static void disable_all_cb(GtkWidget *button, gpointer parent_w);
56 static GtkWidget *proto_w = NULL;
58 /* list of protocols */
59 static GSList *protocol_list = NULL;
61 typedef struct protocol_data {
68 void proto_cb(GtkWidget *w _U_, gpointer data _U_)
71 GtkWidget *main_vb, *bbox, *proto_nb, *apply_bt, *cancel_bt, *ok_bt,
72 *label, *scrolled_w, *selection_vb, *button;
74 if (proto_w != NULL) {
75 reactivate_window(proto_w);
79 proto_w = dlg_window_new("Ethereal: Protocol");
80 SIGNAL_CONNECT(proto_w, "delete_event", proto_delete_cb, NULL);
81 SIGNAL_CONNECT(proto_w, "destroy", proto_destroy_cb, NULL);
82 WIDGET_SET_SIZE(proto_w, DEF_WIDTH * 2/3, DEF_HEIGHT * 2/3);
84 /* Container for each row of widgets */
86 main_vb = gtk_vbox_new(FALSE, 0);
87 gtk_container_border_width(GTK_CONTAINER(main_vb), 1);
88 gtk_container_add(GTK_CONTAINER(proto_w), main_vb);
89 gtk_widget_show(main_vb);
91 /* Protocol topics container */
93 proto_nb = gtk_notebook_new();
94 gtk_container_add(GTK_CONTAINER(main_vb), proto_nb);
95 /* XXX do not know why I need this to fill all space around buttons */
96 WIDGET_SET_SIZE(proto_nb, DEF_WIDTH * 2/3 - 50, DEF_HEIGHT * 2/3 - 50);
98 /* Protocol selection panel ("enable/disable" protocols) */
100 selection_vb = gtk_vbox_new(FALSE, 0);
101 gtk_container_border_width(GTK_CONTAINER(selection_vb), 1);
102 label = gtk_label_new("Button pressed: protocol decoding is enabled");
103 gtk_widget_show(label);
104 gtk_box_pack_start(GTK_BOX(selection_vb), label, FALSE, FALSE, 0);
105 scrolled_w = scrolled_window_new(NULL, NULL);
106 gtk_container_set_border_width(GTK_CONTAINER(scrolled_w), 1);
107 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_w),
108 GTK_POLICY_AUTOMATIC,
110 gtk_box_pack_start(GTK_BOX(selection_vb), scrolled_w, TRUE, TRUE, 0);
111 show_proto_selection(proto_w, scrolled_w);
112 gtk_widget_show(scrolled_w);
113 gtk_widget_show(selection_vb);
114 label = gtk_label_new("Decoding");
115 gtk_notebook_append_page(GTK_NOTEBOOK(proto_nb), selection_vb, label);
116 label = gtk_label_new("Note that when a protocol is disabled, "
117 "all linked sub-protocols are as well");
118 gtk_widget_show(label);
119 gtk_box_pack_start(GTK_BOX(selection_vb), label, FALSE, FALSE, 0);
122 bbox = gtk_hbutton_box_new();
123 gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_END);
124 gtk_button_box_set_spacing(GTK_BUTTON_BOX(bbox), 5);
125 gtk_box_pack_start(GTK_BOX(selection_vb), bbox, FALSE, FALSE, 0);
126 gtk_widget_show(bbox);
129 button = gtk_button_new_with_label("Toggle All");
130 SIGNAL_CONNECT(button, "clicked", toggle_all_cb, proto_w);
131 gtk_box_pack_start(GTK_BOX(bbox), button, TRUE, TRUE, 0);
132 gtk_widget_show(button);
135 button = gtk_button_new_with_label("Enable All");
136 SIGNAL_CONNECT(button, "clicked", enable_all_cb, proto_w);
137 gtk_box_pack_start(GTK_BOX(bbox), button, TRUE, TRUE, 0);
138 gtk_widget_show(button);
141 button = gtk_button_new_with_label("Disable All");
142 SIGNAL_CONNECT(button, "clicked", disable_all_cb, proto_w);
143 gtk_box_pack_start(GTK_BOX(bbox), button, TRUE, TRUE, 0);
144 gtk_widget_show(button);
147 /* XXX add other protocol-related panels here ... */
149 gtk_widget_show(proto_nb);
151 /* Ok, Apply, Cancel Buttons */
153 bbox = gtk_hbutton_box_new();
154 gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_END);
155 gtk_button_box_set_spacing(GTK_BUTTON_BOX(bbox), 5);
156 gtk_container_add(GTK_CONTAINER(main_vb), bbox);
157 gtk_widget_show(bbox);
159 #if GTK_MAJOR_VERSION < 2
160 ok_bt = gtk_button_new_with_label ("OK");
162 ok_bt = gtk_button_new_from_stock(GTK_STOCK_OK);
164 SIGNAL_CONNECT(ok_bt, "clicked", proto_ok_cb, proto_w);
165 GTK_WIDGET_SET_FLAGS(ok_bt, GTK_CAN_DEFAULT);
166 gtk_box_pack_start(GTK_BOX (bbox), ok_bt, TRUE, TRUE, 0);
167 gtk_widget_grab_default(ok_bt);
168 gtk_widget_show(ok_bt);
170 #if GTK_MAJOR_VERSION < 2
171 apply_bt = gtk_button_new_with_label ("Apply");
173 apply_bt = gtk_button_new_from_stock(GTK_STOCK_APPLY);
175 SIGNAL_CONNECT(apply_bt, "clicked", proto_apply_cb, proto_w);
176 GTK_WIDGET_SET_FLAGS(apply_bt, GTK_CAN_DEFAULT);
177 gtk_box_pack_start(GTK_BOX (bbox), apply_bt, TRUE, TRUE, 0);
178 gtk_widget_show(apply_bt);
180 #if GTK_MAJOR_VERSION < 2
181 cancel_bt = gtk_button_new_with_label ("Cancel");
183 cancel_bt = gtk_button_new_from_stock(GTK_STOCK_CANCEL);
185 SIGNAL_CONNECT(cancel_bt, "clicked", proto_cancel_cb, proto_w);
186 GTK_WIDGET_SET_FLAGS(cancel_bt, GTK_CAN_DEFAULT);
187 gtk_box_pack_start(GTK_BOX (bbox), cancel_bt, TRUE, TRUE, 0);
188 gtk_widget_show(cancel_bt);
190 dlg_set_cancel(proto_w, cancel_bt);
192 gtk_quit_add_destroy(gtk_main_level(), proto_w);
193 gtk_widget_show(proto_w);
200 toggle_all_cb(GtkWidget *button _U_, gpointer parent_w)
205 for (entry = protocol_list; entry != NULL; entry = g_slist_next(entry)) {
207 protocol_data_t *p = entry->data;
209 button = (GtkWidget *)OBJECT_GET_DATA(parent_w, p->abbrev);
210 /* gtk_toggle_button_toggled() didn't work for me... */
211 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button),
212 !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button)));
216 /* Enable/Disable All Helper */
218 set_active_all(gpointer parent_w, gboolean new_state)
223 for (entry = protocol_list; entry != NULL; entry = g_slist_next(entry)) {
225 protocol_data_t *p = entry->data;
227 button = (GtkWidget *)OBJECT_GET_DATA(parent_w, p->abbrev);
228 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), new_state);
234 enable_all_cb(GtkWidget *button _U_, gpointer parent_w)
236 set_active_all(parent_w, TRUE);
241 disable_all_cb(GtkWidget *button _U_, gpointer parent_w)
243 set_active_all(parent_w, FALSE);
246 static void proto_destroy_cb(GtkWidget *w _U_, gpointer data _U_)
251 gtk_widget_destroy(proto_w);
254 /* remove protocol list */
256 for (entry = protocol_list; entry != NULL; entry = g_slist_next(entry)) {
259 g_slist_free(protocol_list);
260 protocol_list = NULL;
264 /* Treat this as a cancel, by calling "proto_cancel_cb()".
265 XXX - that'll destroy the Protocols dialog; will that upset
266 a higher-level handler that says "OK, we've been asked to delete
267 this, so destroy it"? */
268 static gboolean proto_delete_cb(GtkWidget *proto_w, gpointer dummy _U_)
270 proto_cancel_cb(NULL, proto_w);
274 static void proto_ok_cb(GtkWidget *ok_bt _U_, gpointer parent_w)
278 redissect = set_proto_selection(GTK_WIDGET(parent_w));
279 gtk_widget_destroy(GTK_WIDGET(parent_w));
281 redissect_packets(&cfile);
284 static void proto_apply_cb(GtkWidget *apply_bt _U_, gpointer parent_w)
286 if (set_proto_selection(GTK_WIDGET(parent_w)))
287 redissect_packets(&cfile);
290 static void proto_cancel_cb(GtkWidget *cancel_bt _U_, gpointer parent_w)
294 redissect = revert_proto_selection();
295 gtk_widget_destroy(GTK_WIDGET(parent_w));
297 redissect_packets(&cfile);
300 static gboolean set_proto_selection(GtkWidget *parent_w)
303 gboolean need_redissect = FALSE;
305 for (entry = protocol_list; entry != NULL; entry = g_slist_next(entry)) {
307 protocol_data_t *p = entry->data;
309 button = (GtkWidget *)OBJECT_GET_DATA(parent_w, p->abbrev);
310 if (proto_is_protocol_enabled(p->hfinfo_index) != GTK_TOGGLE_BUTTON (button)->active) {
311 proto_set_decoding(p->hfinfo_index, GTK_TOGGLE_BUTTON (button)->active);
312 need_redissect = TRUE;
316 return need_redissect;
318 } /* set_proto_selection */
320 static gboolean revert_proto_selection(void)
323 gboolean need_redissect = FALSE;
326 * Undo all the changes we've made to protocol enable flags.
328 for (entry = protocol_list; entry != NULL; entry = g_slist_next(entry)) {
329 protocol_data_t *p = entry->data;
331 if (proto_is_protocol_enabled(p->hfinfo_index) != p->was_enabled) {
332 proto_set_decoding(p->hfinfo_index, p->was_enabled);
333 need_redissect = TRUE;
337 return need_redissect;
339 } /* revert_proto_selection */
341 gint protocol_data_compare(gconstpointer a, gconstpointer b)
343 return strcmp(((protocol_data_t *)a)->abbrev,
344 ((protocol_data_t *)b)->abbrev);
347 static void show_proto_selection(GtkWidget *main, GtkWidget *container)
353 GtkTooltips *tooltips;
355 int i, t = 0, l = 0, nb_line, nb_proto = 0;
359 /* Iterate over all the protocols */
361 for (i = proto_get_first_protocol(&cookie); i != -1;
362 i = proto_get_next_protocol(&cookie)) {
363 if (proto_can_disable_protocol(i)) {
364 p = g_malloc(sizeof(protocol_data_t));
365 p->name = proto_get_protocol_name(i);
366 p->abbrev = proto_get_protocol_filter_name(i);
368 p->was_enabled = proto_is_protocol_enabled(i);
369 protocol_list = g_slist_insert_sorted(protocol_list,
370 p, protocol_data_compare);
375 /* create a table (n x NB_COL) of buttons */
377 nb_line = (nb_proto % NB_COL) ? nb_proto / NB_COL + 1 : nb_proto / NB_COL;
378 table = gtk_table_new (nb_line, NB_COL, FALSE);
379 gtk_table_set_row_spacings(GTK_TABLE (table), 1);
380 gtk_table_set_col_spacings(GTK_TABLE (table), 1);
381 gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(container), table);
382 gtk_widget_show(table);
384 tooltips = gtk_tooltips_new();
388 for (entry = protocol_list; entry != NULL; entry = g_slist_next(entry)) {
392 /* button label is the protocol abbrev */
393 button = gtk_toggle_button_new_with_label(p->abbrev);
394 /* tip is the complete protocol name */
395 gtk_tooltips_set_tip(tooltips, button, p->name, NULL);
396 gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(button),
397 proto_is_protocol_enabled(p->hfinfo_index));
398 OBJECT_SET_DATA(main, p->abbrev, button);
399 gtk_table_attach_defaults (GTK_TABLE (table), button, l, l+1, t, t+1);
400 gtk_widget_show (button);
401 if (++nb_proto % NB_COL) {
410 } /* show_proto_selection */