2 * Routines for handling preferences
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
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.
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.
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.
33 #include <epan/filesystem.h>
36 #include <epan/packet.h>
38 #include <epan/prefs.h>
39 #include "column_prefs.h"
41 #include "prefs_dlg.h"
42 #include "print_prefs.h"
43 #include "stream_prefs.h"
44 #include "gui_prefs.h"
45 #include "layout_prefs.h"
46 #include "capture_prefs.h"
47 #include "nameres_prefs.h"
48 #include "gui_utils.h"
49 #include "dlg_utils.h"
50 #include "simple_dialog.h"
51 #include "compat_macros.h"
55 #include <epan/prefs-int.h>
59 #include "capture-wpcap.h"
63 #include "airpcap_loader.h"
64 #include "airpcap_gui_utils.h"
68 static void prefs_main_ok_cb(GtkWidget *, gpointer);
69 static void prefs_main_apply_cb(GtkWidget *, gpointer);
70 static void prefs_main_save_cb(GtkWidget *, gpointer);
71 static void prefs_main_cancel_cb(GtkWidget *, gpointer);
72 static gboolean prefs_main_delete_event_cb(GtkWidget *, GdkEvent *, gpointer);
73 static void prefs_main_destroy_cb(GtkWidget *, gpointer);
74 #if GTK_MAJOR_VERSION < 2
75 static void prefs_tree_select_cb(GtkCTree *, GtkCTreeNode *, gint,
78 static void prefs_tree_select_cb(GtkTreeSelection *, gpointer);
81 #define E_PREFSW_SCROLLW_KEY "prefsw_scrollw"
82 #define E_PREFSW_TREE_KEY "prefsw_tree"
83 #define E_PREFSW_NOTEBOOK_KEY "prefsw_notebook"
84 #define E_PREFSW_SAVE_BT_KEY "prefsw_save_bt"
85 #define E_PAGE_ITER_KEY "page_iter"
86 #define E_PAGE_MODULE_KEY "page_module"
87 #define E_PAGESW_FRAME_KEY "pagesw_frame"
89 #define E_GUI_PAGE_KEY "gui_options_page"
90 #define E_GUI_LAYOUT_PAGE_KEY "gui_layout_page"
91 #define E_GUI_COLUMN_PAGE_KEY "gui_column_options_page"
92 #define E_GUI_FONT_PAGE_KEY "gui_font_options_page"
93 #define E_GUI_COLORS_PAGE_KEY "gui_colors_options_page"
94 #define E_CAPTURE_PAGE_KEY "capture_options_page"
95 #define E_PRINT_PAGE_KEY "printer_options_page"
96 #define E_NAMERES_PAGE_KEY "nameres_options_page"
99 * Keep a static pointer to the current "Preferences" window, if any, so that
100 * if somebody tries to do "Edit:Preferences" while there's already a
101 * "Preferences" window up, we just pop up the existing one, rather than
102 * creating a new one.
104 static GtkWidget *prefs_w;
107 * Save the value of the preferences as of when the preferences dialog
108 * box was first popped up, so we can revert to those values if the
109 * user selects "Cancel".
111 static e_prefs saved_prefs;
117 #if GTK_MAJOR_VERSION < 2
122 GtkTooltips *tooltips;
124 gboolean is_protocol;
128 pref_exists(pref_t *pref _U_, gpointer user_data _U_)
133 /* show a single preference on the GtkTable of a preference page */
135 pref_show(pref_t *pref, gpointer user_data)
137 GtkWidget *main_tb = user_data;
142 /* Give this preference a label which is its title, followed by a colon,
143 and left-align it. */
145 label_string = g_malloc(strlen(title) + 2);
146 strcpy(label_string, title);
147 strcat(label_string, ":");
149 /* Save the current value of the preference, so that we can revert it if
150 the user does "Apply" and then "Cancel", and create the control for
151 editing the preference. */
152 switch (pref->type) {
155 pref->saved_val.uint = *pref->varp.uint;
157 /* XXX - there are no uint spinbuttons, so we can't use a spinbutton.
158 Even more annoyingly, even if there were, GLib doesn't define
159 G_MAXUINT - but I think ANSI C may define UINT_MAX, so we could
161 switch (pref->info.base) {
164 g_snprintf(uint_str, 10+1, "%u", pref->saved_val.uint);
168 g_snprintf(uint_str, 10+1, "%o", pref->saved_val.uint);
172 g_snprintf(uint_str, 10+1, "%x", pref->saved_val.uint);
175 pref->control = create_preference_entry(main_tb, pref->ordinal,
176 label_string, pref->description,
181 pref->saved_val.boolval = *pref->varp.boolp;
182 pref->control = create_preference_check_button(main_tb, pref->ordinal,
183 label_string, pref->description,
184 pref->saved_val.boolval);
188 pref->saved_val.enumval = *pref->varp.enump;
189 if (pref->info.enum_info.radio_buttons) {
190 /* Show it as radio buttons. */
191 pref->control = create_preference_radio_buttons(main_tb, pref->ordinal,
192 label_string, pref->description,
193 pref->info.enum_info.enumvals,
194 pref->saved_val.enumval);
196 /* Show it as an option menu. */
197 pref->control = create_preference_option_menu(main_tb, pref->ordinal,
198 label_string, pref->description,
199 pref->info.enum_info.enumvals,
200 pref->saved_val.enumval);
205 if (pref->saved_val.string != NULL)
206 g_free(pref->saved_val.string);
207 pref->saved_val.string = g_strdup(*pref->varp.string);
208 pref->control = create_preference_entry(main_tb, pref->ordinal,
209 label_string, pref->description,
210 pref->saved_val.string);
217 if (pref->saved_val.range != NULL)
218 g_free(pref->saved_val.range);
219 pref->saved_val.range = range_copy(*pref->varp.range);
220 range_string = range_convert_range(*pref->varp.range);
221 pref->control = create_preference_entry(main_tb, pref->ordinal,
222 label_string, pref->description,
228 g_assert_not_reached();
231 g_free(label_string);
236 #define MAX_TREE_NODE_NAME_LEN 64
237 /* show prefs page for each registered module (protocol) */
239 module_prefs_show(module_t *module, gpointer user_data)
241 struct ct_struct *cts = user_data;
242 struct ct_struct child_cts;
243 GtkWidget *main_vb, *main_tb, *frame, *main_sw;
244 gchar label_str[MAX_TREE_NODE_NAME_LEN];
245 #if GTK_MAJOR_VERSION < 2
246 gchar *label_ptr = label_str;
247 GtkCTreeNode *ct_node;
254 * Is this module a subtree, with modules underneath it?
256 if (!module->is_subtree) {
259 * Does it have any preferences (other than possibly obsolete ones)?
261 if (prefs_pref_foreach(module, pref_exists, NULL) == 0) {
263 * No. Don't put the module into the preferences window.
264 * XXX - we should do the same for subtrees; if a subtree has
265 * nothing under it that will be displayed, don't put it into
273 * Add this module to the tree.
275 strcpy(label_str, module->title);
276 #if GTK_MAJOR_VERSION < 2
277 ct_node = gtk_ctree_insert_node(GTK_CTREE(cts->tree), cts->node, NULL,
278 &label_ptr, 5, NULL, NULL, NULL, NULL, !module->is_subtree,
281 model = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(cts->tree)));
282 if (module->is_subtree)
283 gtk_tree_store_append(model, &iter, NULL);
285 gtk_tree_store_append(model, &iter, &cts->iter);
291 if (module->is_subtree) {
296 /* Note that there's no page attached to this item */
297 #if GTK_MAJOR_VERSION < 2
298 gtk_ctree_node_set_row_data(GTK_CTREE(cts->tree), ct_node,
299 GINT_TO_POINTER(-1));
301 gtk_tree_store_set(model, &iter, 0, label_str, 1, -1, -1);
305 * Walk the subtree and attach stuff to it.
308 #if GTK_MAJOR_VERSION < 2
309 child_cts.node = ct_node;
311 child_cts.iter = iter;
313 if (module == protocols_module)
314 child_cts.is_protocol = TRUE;
315 prefs_module_list_foreach(module->prefs, module_prefs_show, &child_cts);
318 * No. Create a notebook page for it.
321 /* Scrolled window */
322 main_sw = gtk_scrolled_window_new(NULL, NULL);
323 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(main_sw), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
326 frame = gtk_frame_new(module->description);
327 gtk_container_set_border_width(GTK_CONTAINER(frame), 5);
328 gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(main_sw), frame);
329 OBJECT_SET_DATA(main_sw, E_PAGESW_FRAME_KEY, frame);
331 /* Main vertical box */
332 main_vb = gtk_vbox_new(FALSE, 5);
333 gtk_container_border_width(GTK_CONTAINER(main_vb), 5);
334 gtk_container_add(GTK_CONTAINER(frame), main_vb);
337 main_tb = gtk_table_new(module->numprefs, 2, FALSE);
338 gtk_box_pack_start(GTK_BOX(main_vb), main_tb, FALSE, FALSE, 0);
339 gtk_table_set_row_spacings(GTK_TABLE(main_tb), 10);
340 gtk_table_set_col_spacings(GTK_TABLE(main_tb), 15);
341 OBJECT_SET_DATA(main_tb, E_TOOLTIPS_KEY, cts->tooltips);
343 /* Add items for each of the preferences */
344 prefs_pref_foreach(module, pref_show, main_tb);
346 /* Associate this module with the page's frame. */
347 OBJECT_SET_DATA(frame, E_PAGE_MODULE_KEY, module);
349 /* Add the page to the notebook */
350 gtk_notebook_append_page(GTK_NOTEBOOK(cts->notebook), main_sw, NULL);
352 /* Attach the page to the tree item */
353 #if GTK_MAJOR_VERSION < 2
354 gtk_ctree_node_set_row_data(GTK_CTREE(cts->tree), ct_node,
355 GINT_TO_POINTER(cts->page));
356 OBJECT_SET_DATA(frame, E_PAGE_ITER_KEY, ct_node);
358 gtk_tree_store_set(model, &iter, 0, label_str, 1, cts->page, -1);
359 OBJECT_SET_DATA(frame, E_PAGE_ITER_KEY, gtk_tree_iter_copy(&iter));
364 /* Show 'em what we got */
365 gtk_widget_show_all(main_sw);
372 #if GTK_MAJOR_VERSION < 2
373 #define prefs_tree_iter GtkCTreeNode *
375 #define prefs_tree_iter GtkTreeIter
378 /* add a page to the tree */
379 static prefs_tree_iter
380 prefs_tree_page_add(const gchar *title, gint page_nr,
381 gpointer store, prefs_tree_iter *parent_iter,
383 #if GTK_MAJOR_VERSION >= 2
388 #if GTK_MAJOR_VERSION < 2
389 const gchar *label_ptr = title;
391 prefs_tree_iter iter;
393 #if GTK_MAJOR_VERSION < 2
394 iter = gtk_ctree_insert_node(GTK_CTREE(store), parent_iter ? *parent_iter : NULL, NULL,
395 (gchar **) &label_ptr, 5, NULL, NULL, NULL, NULL, !has_child, TRUE);
396 gtk_ctree_node_set_row_data(GTK_CTREE(store), iter,
397 GINT_TO_POINTER(page_nr));
399 gtk_tree_store_append(store, &iter, parent_iter);
400 gtk_tree_store_set(store, &iter, 0, title, 1, page_nr, -1);
405 /* add a page to the notebook */
407 prefs_nb_page_add(GtkWidget *notebook, const gchar *title, GtkWidget *page, const char *page_key)
411 frame = gtk_frame_new(title);
412 gtk_widget_show(frame);
413 gtk_container_add(GTK_CONTAINER(frame), page);
414 OBJECT_SET_DATA(prefs_w, page_key, page);
415 gtk_notebook_append_page (GTK_NOTEBOOK(notebook), frame, NULL);
421 /* show the dialog */
423 prefs_cb(GtkWidget *w _U_, gpointer dummy _U_)
425 GtkWidget *top_hb, *bbox, *prefs_nb, *ct_sb,
426 *ok_bt, *apply_bt, *save_bt, *cancel_bt, *help_bt;
427 GtkWidget *gui_font_pg;
428 gchar label_str[MAX_TREE_NODE_NAME_LEN];
429 struct ct_struct cts;
430 #if GTK_MAJOR_VERSION < 2
431 gpointer store = NULL;
432 static gchar *fixedwidths[] = { "c", "m", NULL };
435 GtkTreeSelection *selection;
436 GtkCellRenderer *renderer;
437 GtkTreeViewColumn *column;
440 prefs_tree_iter gui_iter;
443 if (prefs_w != NULL) {
444 /* There's already a "Preferences" dialog box; reactivate it. */
445 reactivate_window(prefs_w);
449 /* Save the current preferences, so we can revert to those values
450 if the user presses "Cancel". */
451 copy_prefs(&saved_prefs, &prefs);
453 prefs_w = dlg_window_new("Wireshark: Preferences");
456 * Unfortunately, we can't arrange that a GtkTable widget wrap an event box
457 * around a table row, so the spacing between the preference item's label
458 * and its control widgets is inactive and the tooltip doesn't pop up when
459 * the mouse is over it.
461 cts.tooltips = gtk_tooltips_new();
463 /* Container for each row of widgets */
464 cts.main_vb = gtk_vbox_new(FALSE, 5);
465 gtk_container_border_width(GTK_CONTAINER(cts.main_vb), 5);
466 gtk_container_add(GTK_CONTAINER(prefs_w), cts.main_vb);
467 gtk_widget_show(cts.main_vb);
469 /* Top row: Preferences tree and notebook */
470 top_hb = gtk_hbox_new(FALSE, 10);
471 gtk_container_add(GTK_CONTAINER(cts.main_vb), top_hb);
472 gtk_widget_show(top_hb);
474 /* scrolled window on the left for the categories tree */
475 ct_sb = scrolled_window_new(NULL, NULL);
476 #if GTK_MAJOR_VERSION >= 2
477 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(ct_sb),
480 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(ct_sb),
481 GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
482 gtk_container_add(GTK_CONTAINER(top_hb), ct_sb);
483 gtk_widget_show(ct_sb);
484 OBJECT_SET_DATA(prefs_w, E_PREFSW_SCROLLW_KEY, ct_sb);
486 /* categories tree */
487 #if GTK_MAJOR_VERSION < 2
488 cts.tree = ctree_new(1, 0);
491 gtk_clist_set_column_auto_resize(GTK_CLIST(cts.tree), 0, TRUE);
492 SIGNAL_CONNECT(cts.tree, "tree-select-row", prefs_tree_select_cb, NULL);
493 OBJECT_SET_DATA(prefs_w, E_PREFSW_TREE_KEY, cts.tree);
495 store = gtk_tree_store_new(2, G_TYPE_STRING, G_TYPE_INT);
496 cts.tree = tree_view_new(GTK_TREE_MODEL(store));
497 OBJECT_SET_DATA(prefs_w, E_PREFSW_TREE_KEY, cts.tree);
498 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(cts.tree), FALSE);
499 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(cts.tree));
500 gtk_tree_selection_set_mode(selection, GTK_SELECTION_SINGLE);
501 renderer = gtk_cell_renderer_text_new();
502 col_offset = gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(cts.tree),
503 -1, "Name", renderer,
505 column = gtk_tree_view_get_column(GTK_TREE_VIEW(cts.tree),
507 gtk_tree_view_column_set_sizing(GTK_TREE_VIEW_COLUMN(column),
508 GTK_TREE_VIEW_COLUMN_AUTOSIZE);
509 SIGNAL_CONNECT(selection, "changed", prefs_tree_select_cb, NULL);
511 gtk_container_add(GTK_CONTAINER(ct_sb), cts.tree);
512 gtk_widget_show(cts.tree);
514 /* A notebook widget without tabs is used to flip between prefs */
515 prefs_nb = gtk_notebook_new();
516 OBJECT_SET_DATA(prefs_w, E_PREFSW_NOTEBOOK_KEY, prefs_nb);
517 gtk_notebook_set_show_tabs(GTK_NOTEBOOK(prefs_nb), FALSE);
518 gtk_notebook_set_show_border(GTK_NOTEBOOK(prefs_nb), FALSE);
519 gtk_container_add(GTK_CONTAINER(top_hb), prefs_nb);
520 gtk_widget_show(prefs_nb);
525 strcpy(label_str, "User Interface");
526 prefs_nb_page_add(prefs_nb, label_str, gui_prefs_show(), E_GUI_PAGE_KEY);
527 gui_iter = prefs_tree_page_add(label_str, cts.page, store, NULL, TRUE);
530 /* GUI layout prefs */
531 strcpy(label_str, "Layout");
532 prefs_nb_page_add(prefs_nb, label_str, layout_prefs_show(), E_GUI_LAYOUT_PAGE_KEY);
533 prefs_tree_page_add(label_str, cts.page, store, &gui_iter, FALSE);
536 /* GUI Column prefs */
537 strcpy(label_str, "Columns");
538 prefs_nb_page_add(prefs_nb, label_str, column_prefs_show(), E_GUI_COLUMN_PAGE_KEY);
539 prefs_tree_page_add(label_str, cts.page, store, &gui_iter, FALSE);
543 strcpy(label_str, "Font");
544 gui_font_pg = gui_font_prefs_show();
545 prefs_nb_page_add(prefs_nb, label_str, gui_font_pg, E_GUI_FONT_PAGE_KEY);
546 prefs_tree_page_add(label_str, cts.page, store, &gui_iter, FALSE);
549 gtk_container_border_width( GTK_CONTAINER(gui_font_pg), 5 );
551 /* IMPORTANT: the following gtk_font_selection_set_xy() functions will only
552 work, if the widget and it's corresponding window is already shown
553 (so don't put the following into gui_font_prefs_show()) !!! */
555 /* We set the current font and, for GTK+ 1.2[.x], the font filter
556 now, because they appear not to work when run before appending
557 the frame to the notebook. */
559 /* Set the font to the current font.
560 XXX - GTK+ 1.2.8, and probably earlier versions, have a bug
561 wherein that doesn't necessarily cause that font to be
562 selected in the dialog box. I've sent to the GTK+ folk
563 a fix; hopefully, it'll show up in 1.2.9 if, as, and when
564 they put out a 1.2.9 release. */
565 gtk_font_selection_set_font_name(
566 GTK_FONT_SELECTION(gui_font_pg), prefs.PREFS_GUI_FONT_NAME);
568 #if GTK_MAJOR_VERSION < 2
569 /* Set its filter to show only fixed_width fonts. */
570 gtk_font_selection_set_filter(
571 GTK_FONT_SELECTION(gui_font_pg),
572 GTK_FONT_FILTER_BASE, /* user can't change the filter */
573 GTK_FONT_ALL, /* bitmap or scalable are fine */
574 NULL, /* all foundries are OK */
575 NULL, /* all weights are OK (XXX - normal only?) */
576 NULL, /* all slants are OK (XXX - Roman only?) */
577 NULL, /* all setwidths are OK */
578 fixedwidths, /* ONLY fixed-width fonts */
579 NULL); /* all charsets are OK (XXX - ISO 8859/1 only?) */
582 /* GUI Colors prefs */
583 strcpy(label_str, "Colors");
584 prefs_nb_page_add(prefs_nb, label_str, stream_prefs_show(), E_GUI_COLORS_PAGE_KEY);
585 prefs_tree_page_add(label_str, cts.page, store, &gui_iter, FALSE);
588 /* select the main GUI page as the default page and expand it's children */
589 #if GTK_MAJOR_VERSION < 2
590 gtk_ctree_select(GTK_CTREE(cts.tree), gui_iter);
592 gtk_tree_selection_select_iter(selection, &gui_iter);
593 /* (expand will only take effect, when at least one child exists) */
594 gtk_tree_view_expand_all(GTK_TREE_VIEW(cts.tree));
599 /* Is WPcap loaded? */
603 strcpy(label_str, "Capture");
604 prefs_nb_page_add(prefs_nb, label_str, capture_prefs_show(), E_CAPTURE_PAGE_KEY);
605 prefs_tree_page_add(label_str, cts.page, store, NULL, FALSE);
610 #endif /* HAVE_LIBPCAP */
613 strcpy(label_str, "Printing");
614 prefs_nb_page_add(prefs_nb, label_str, printer_prefs_show(), E_PRINT_PAGE_KEY);
615 prefs_tree_page_add(label_str, cts.page, store, NULL, FALSE);
618 /* Name resolution prefs */
619 strcpy(label_str, "Name Resolution");
620 prefs_nb_page_add(prefs_nb, label_str, nameres_prefs_show(), E_NAMERES_PAGE_KEY);
621 prefs_tree_page_add(label_str, cts.page, store, NULL, FALSE);
624 /* Registered prefs */
625 cts.notebook = prefs_nb;
626 cts.is_protocol = FALSE;
627 prefs_module_list_foreach(NULL, module_prefs_show, &cts);
629 /* Button row: OK and alike buttons */
631 if(topic_available(HELP_PREFERENCES_DIALOG)) {
632 bbox = dlg_button_row_new(GTK_STOCK_HELP, GTK_STOCK_OK, GTK_STOCK_APPLY, GTK_STOCK_SAVE, GTK_STOCK_CANCEL, NULL);
634 bbox = dlg_button_row_new(GTK_STOCK_OK, GTK_STOCK_APPLY, GTK_STOCK_SAVE, GTK_STOCK_CANCEL, NULL);
636 gtk_box_pack_start(GTK_BOX(cts.main_vb), bbox, FALSE, FALSE, 0);
637 gtk_widget_show(bbox);
639 ok_bt = OBJECT_GET_DATA(bbox, GTK_STOCK_OK);
640 SIGNAL_CONNECT(ok_bt, "clicked", prefs_main_ok_cb, prefs_w);
642 apply_bt = OBJECT_GET_DATA(bbox, GTK_STOCK_APPLY);
643 SIGNAL_CONNECT(apply_bt, "clicked", prefs_main_apply_cb, prefs_w);
645 save_bt = OBJECT_GET_DATA(bbox, GTK_STOCK_SAVE);
646 SIGNAL_CONNECT(save_bt, "clicked", prefs_main_save_cb, prefs_w);
647 OBJECT_SET_DATA(prefs_w, E_PREFSW_SAVE_BT_KEY, save_bt);
649 cancel_bt = OBJECT_GET_DATA(bbox, GTK_STOCK_CANCEL);
650 SIGNAL_CONNECT(cancel_bt, "clicked", prefs_main_cancel_cb, prefs_w);
651 window_set_cancel_button(prefs_w, cancel_bt, NULL);
653 gtk_widget_grab_default(ok_bt);
655 if(topic_available(HELP_PREFERENCES_DIALOG)) {
656 help_bt = OBJECT_GET_DATA(bbox, GTK_STOCK_HELP);
657 SIGNAL_CONNECT(help_bt, "clicked", topic_cb, HELP_PREFERENCES_DIALOG);
660 SIGNAL_CONNECT(prefs_w, "delete_event", prefs_main_delete_event_cb, prefs_w);
661 SIGNAL_CONNECT(prefs_w, "destroy", prefs_main_destroy_cb, prefs_w);
663 gtk_widget_show(prefs_w);
665 /* hide the Save button if the user uses implicit save */
666 if(!prefs.gui_use_pref_save) {
667 gtk_widget_hide(save_bt);
670 window_present(prefs_w);
672 #if GTK_MAJOR_VERSION >= 2
673 g_object_unref(G_OBJECT(store));
678 set_option_label(GtkWidget *main_tb, int table_position,
679 const gchar *label_text, const gchar *tooltip_text, GtkTooltips *tooltips)
682 GtkWidget *event_box;
684 label = gtk_label_new(label_text);
685 gtk_misc_set_alignment(GTK_MISC(label), 1.0, 0.5);
686 gtk_widget_show(label);
688 event_box = gtk_event_box_new();
689 gtk_table_attach_defaults(GTK_TABLE(main_tb), event_box, 0, 1,
690 table_position, table_position + 1);
691 if (tooltip_text != NULL && tooltips != NULL)
692 gtk_tooltips_set_tip(tooltips, event_box, tooltip_text, NULL);
693 gtk_container_add(GTK_CONTAINER(event_box), label);
694 gtk_widget_show(event_box);
698 create_preference_check_button(GtkWidget *main_tb, int table_position,
699 const gchar *label_text, const gchar *tooltip_text, gboolean active)
701 GtkTooltips *tooltips;
702 GtkWidget *check_box;
704 tooltips = OBJECT_GET_DATA(main_tb, E_TOOLTIPS_KEY);
706 set_option_label(main_tb, table_position, label_text, tooltip_text,
709 check_box = gtk_check_button_new();
710 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check_box), active);
711 gtk_table_attach_defaults(GTK_TABLE(main_tb), check_box, 1, 2,
712 table_position, table_position + 1);
713 if (tooltip_text != NULL && tooltips != NULL)
714 gtk_tooltips_set_tip(tooltips, check_box, tooltip_text, NULL);
720 create_preference_radio_buttons(GtkWidget *main_tb, int table_position,
721 const gchar *label_text, const gchar *tooltip_text,
722 const enum_val_t *enumvals, gint current_val)
724 GtkTooltips *tooltips;
725 GtkWidget *radio_button_hbox, *button = NULL;
728 const enum_val_t *enum_valp;
729 GtkWidget *event_box;
731 tooltips = OBJECT_GET_DATA(main_tb, E_TOOLTIPS_KEY);
733 set_option_label(main_tb, table_position, label_text, tooltip_text,
736 radio_button_hbox = gtk_hbox_new(FALSE, 0);
738 for (enum_valp = enumvals, index = 0; enum_valp->name != NULL;
739 enum_valp++, index++) {
740 button = gtk_radio_button_new_with_label(rb_group,
741 enum_valp->description);
742 gtk_widget_show(button);
743 rb_group = gtk_radio_button_group(GTK_RADIO_BUTTON(button));
744 gtk_box_pack_start(GTK_BOX(radio_button_hbox), button, FALSE,
746 if (enum_valp->value == current_val) {
747 gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(button),
751 gtk_widget_show(radio_button_hbox);
753 event_box = gtk_event_box_new();
754 gtk_container_add(GTK_CONTAINER(event_box), radio_button_hbox);
755 gtk_table_attach_defaults(GTK_TABLE(main_tb), event_box, 1, 2,
756 table_position, table_position+1);
757 if (tooltip_text != NULL && tooltips != NULL)
758 gtk_tooltips_set_tip(tooltips, event_box, tooltip_text, NULL);
759 gtk_widget_show(event_box);
762 * It doesn't matter which of the buttons we return - we fetch
763 * the value by looking at the entire radio button group to
764 * which it belongs, and we can get that from any button.
770 label_to_enum_val(GtkWidget *label, const enum_val_t *enumvals)
775 /* Get the label's text, and translate it to a value.
776 We match only the descriptions, as those are what appear in
777 the option menu items or as labels for radio buttons.
778 We fail if we don't find a match, as that "can't happen". */
779 gtk_label_get(GTK_LABEL(label), &label_string);
781 for (i = 0; enumvals[i].name != NULL; i++) {
782 if (strcasecmp(label_string, enumvals[i].description) == 0) {
783 return enumvals[i].value;
786 g_assert_not_reached();
791 fetch_preference_radio_buttons_val(GtkWidget *button,
792 const enum_val_t *enumvals)
798 * Go through the list of of radio buttons in the button's group,
799 * and find the first one that's active.
801 rb_group = gtk_radio_button_group(GTK_RADIO_BUTTON(button));
803 for (rb_entry = rb_group; rb_entry != NULL;
804 rb_entry = g_slist_next(rb_entry)) {
805 button = rb_entry->data;
806 if (GTK_TOGGLE_BUTTON(button)->active)
810 /* OK, now return the value corresponding to that button's label. */
811 return label_to_enum_val(GTK_BIN(button)->child, enumvals);
815 create_preference_option_menu(GtkWidget *main_tb, int table_position,
816 const gchar *label_text, const gchar *tooltip_text,
817 const enum_val_t *enumvals, gint current_val)
819 GtkTooltips *tooltips;
820 GtkWidget *menu_box, *menu, *menu_item, *option_menu;
821 int menu_index, index;
822 const enum_val_t *enum_valp;
823 GtkWidget *event_box;
825 tooltips = OBJECT_GET_DATA(main_tb, E_TOOLTIPS_KEY);
827 set_option_label(main_tb, table_position, label_text, tooltip_text,
830 /* Create a menu from the enumvals */
831 menu = gtk_menu_new();
832 if (tooltip_text != NULL && tooltips != NULL)
833 gtk_tooltips_set_tip(tooltips, menu, tooltip_text, NULL);
835 for (enum_valp = enumvals, index = 0; enum_valp->name != NULL;
836 enum_valp++, index++) {
837 menu_item = gtk_menu_item_new_with_label(enum_valp->description);
838 gtk_menu_append(GTK_MENU(menu), menu_item);
839 if (enum_valp->value == current_val)
841 gtk_widget_show(menu_item);
844 /* Create the option menu from the menu */
845 option_menu = gtk_option_menu_new();
846 gtk_option_menu_set_menu(GTK_OPTION_MENU(option_menu), menu);
848 /* Set its current value to the variable's current value */
849 if (menu_index != -1)
850 gtk_option_menu_set_history(GTK_OPTION_MENU(option_menu),
854 * Put the option menu in an hbox, so that it's only as wide
855 * as the widest entry, rather than being as wide as the table
858 menu_box = gtk_hbox_new(FALSE, 0);
859 gtk_box_pack_start(GTK_BOX(menu_box), option_menu, FALSE, FALSE, 0);
861 event_box = gtk_event_box_new();
862 gtk_table_attach_defaults(GTK_TABLE(main_tb), event_box,
863 1, 2, table_position, table_position + 1);
864 if (tooltip_text != NULL && tooltips != NULL)
865 gtk_tooltips_set_tip(tooltips, event_box, tooltip_text, NULL);
866 gtk_container_add(GTK_CONTAINER(event_box), menu_box);
872 fetch_preference_option_menu_val(GtkWidget *optmenu, const enum_val_t *enumvals)
875 * OK, now return the value corresponding to the label for the
876 * currently active entry in the option menu.
878 * Yes, this is how you get the label for that entry. See FAQ
879 * 6.8 in the GTK+ FAQ.
881 return label_to_enum_val(GTK_BIN(optmenu)->child, enumvals);
885 create_preference_entry(GtkWidget *main_tb, int table_position,
886 const gchar *label_text, const gchar *tooltip_text, char *value)
888 GtkTooltips *tooltips;
891 tooltips = OBJECT_GET_DATA(main_tb, E_TOOLTIPS_KEY);
893 set_option_label(main_tb, table_position, label_text, tooltip_text,
896 entry = gtk_entry_new();
898 gtk_entry_set_text(GTK_ENTRY(entry), value);
899 gtk_table_attach_defaults(GTK_TABLE(main_tb), entry, 1, 2,
900 table_position, table_position + 1);
901 if (tooltip_text != NULL && tooltips != NULL)
902 gtk_tooltips_set_tip(tooltips, entry, tooltip_text, NULL);
903 gtk_widget_show(entry);
909 pref_check(pref_t *pref, gpointer user_data)
914 pref_t **badpref = user_data;
916 /* Fetch the value of the preference, and check whether it's valid. */
917 switch (pref->type) {
920 str_val = gtk_entry_get_text(GTK_ENTRY(pref->control));
921 uval = strtoul(str_val, &p, pref->info.base);
922 if (p == str_val || *p != '\0') {
924 return PREFS_SET_SYNTAX_ERR; /* number was bad */
929 /* Value can't be bad. */
933 /* Value can't be bad. */
937 /* Value can't be bad. */
941 str_val = gtk_entry_get_text(GTK_ENTRY(pref->control));
943 if (strlen(str_val) != 0) {
946 if (range_convert_str(&newrange, str_val, pref->info.max_value) !=
949 return PREFS_SET_SYNTAX_ERR; /* range was bad */
956 g_assert_not_reached();
963 module_prefs_check(module_t *module, gpointer user_data)
965 /* For all preferences in this module, fetch its value from this
966 module's notebook page and check whether it's valid. */
967 return prefs_pref_foreach(module, pref_check, user_data);
971 pref_fetch(pref_t *pref, gpointer user_data)
978 gboolean *pref_changed_p = user_data;
980 /* Fetch the value of the preference, and set the appropriate variable
982 switch (pref->type) {
985 str_val = gtk_entry_get_text(GTK_ENTRY(pref->control));
986 uval = strtoul(str_val, &p, pref->info.base);
988 if (p == value || *p != '\0')
989 return PREFS_SET_SYNTAX_ERR; /* number was bad */
991 if (*pref->varp.uint != uval) {
992 *pref_changed_p = TRUE;
993 *pref->varp.uint = uval;
998 bval = GTK_TOGGLE_BUTTON(pref->control)->active;
999 if (*pref->varp.boolp != bval) {
1000 *pref_changed_p = TRUE;
1001 *pref->varp.boolp = bval;
1006 if (pref->info.enum_info.radio_buttons) {
1007 enumval = fetch_preference_radio_buttons_val(pref->control,
1008 pref->info.enum_info.enumvals);
1010 enumval = fetch_preference_option_menu_val(pref->control,
1011 pref->info.enum_info.enumvals);
1014 if (*pref->varp.enump != enumval) {
1015 *pref_changed_p = TRUE;
1016 *pref->varp.enump = enumval;
1021 str_val = gtk_entry_get_text(GTK_ENTRY(pref->control));
1022 if (strcmp(*pref->varp.string, str_val) != 0) {
1023 *pref_changed_p = TRUE;
1024 g_free((void *)*pref->varp.string);
1025 *pref->varp.string = g_strdup(str_val);
1034 str_val = gtk_entry_get_text(GTK_ENTRY(pref->control));
1035 ret = range_convert_str(&newrange, str_val, pref->info.max_value);
1036 if (ret != CVT_NO_ERROR)
1038 return PREFS_SET_SYNTAX_ERR; /* range was bad */
1040 return 0; /* XXX - should fail */
1043 if (!ranges_are_equal(*pref->varp.range, newrange)) {
1044 *pref_changed_p = TRUE;
1045 g_free(*pref->varp.range);
1046 *pref->varp.range = newrange;
1054 g_assert_not_reached();
1061 module_prefs_fetch(module_t *module, gpointer user_data)
1063 gboolean *must_redissect_p = user_data;
1065 /* For all preferences in this module, fetch its value from this
1066 module's notebook page. Find out whether any of them changed. */
1067 module->prefs_changed = FALSE; /* assume none of them changed */
1068 prefs_pref_foreach(module, pref_fetch, &module->prefs_changed);
1070 /* If any of them changed, indicate that we must redissect and refilter
1071 the current capture (if we have one), as the preference change
1072 could cause packets to be dissected differently. */
1073 if (module->prefs_changed)
1074 *must_redissect_p = TRUE;
1076 return 0; /* keep fetching module preferences */
1081 * This function is used to apply changes and update the Wireless Toolbar
1082 * whenever we apply some changes to the WEP preferences
1085 prefs_airpcap_update()
1087 GtkWidget *decryption_cm;
1088 GtkWidget *decryption_en;
1089 gboolean wireshark_decryption_was_enabled;
1090 gboolean airpcap_decryption_was_enabled;
1091 gboolean wireshark_decryption_is_now_enabled;
1093 decryption_cm = GTK_WIDGET(OBJECT_GET_DATA(airpcap_tb,AIRPCAP_TOOLBAR_DECRYPTION_KEY));
1094 decryption_en = GTK_WIDGET(GTK_ENTRY(GTK_COMBO(decryption_cm)->entry));
1096 if( g_strcasecmp(gtk_entry_get_text(GTK_ENTRY(decryption_en)),AIRPCAP_DECRYPTION_TYPE_STRING_WIRESHARK) == 0 )
1098 wireshark_decryption_was_enabled = TRUE;
1099 airpcap_decryption_was_enabled = FALSE;
1101 else if( g_strcasecmp(gtk_entry_get_text(GTK_ENTRY(decryption_en)),AIRPCAP_DECRYPTION_TYPE_STRING_AIRPCAP) == 0 )
1103 wireshark_decryption_was_enabled = FALSE;
1104 airpcap_decryption_was_enabled = TRUE;
1106 else if( g_strcasecmp(gtk_entry_get_text(GTK_ENTRY(decryption_en)),AIRPCAP_DECRYPTION_TYPE_STRING_NONE) == 0 )
1108 wireshark_decryption_was_enabled = FALSE;
1109 airpcap_decryption_was_enabled = FALSE;
1112 wireshark_decryption_is_now_enabled = wireshark_decryption_on();
1114 if(wireshark_decryption_is_now_enabled && airpcap_decryption_was_enabled)
1116 set_airpcap_decryption(FALSE);
1117 gtk_entry_set_text(GTK_ENTRY(decryption_en),AIRPCAP_DECRYPTION_TYPE_STRING_WIRESHARK);
1119 if(wireshark_decryption_is_now_enabled && !airpcap_decryption_was_enabled)
1121 set_airpcap_decryption(FALSE);
1122 gtk_entry_set_text(GTK_ENTRY(decryption_en),AIRPCAP_DECRYPTION_TYPE_STRING_WIRESHARK);
1124 else if(!wireshark_decryption_is_now_enabled && wireshark_decryption_was_enabled)
1126 if(airpcap_decryption_was_enabled)
1128 set_airpcap_decryption(TRUE);
1129 gtk_entry_set_text(GTK_ENTRY(decryption_en),AIRPCAP_DECRYPTION_TYPE_STRING_AIRPCAP);
1133 set_airpcap_decryption(FALSE);
1134 gtk_entry_set_text(GTK_ENTRY(decryption_en),AIRPCAP_DECRYPTION_TYPE_STRING_NONE);
1141 pref_clean(pref_t *pref, gpointer user_data _U_)
1143 switch (pref->type) {
1155 if (pref->saved_val.string != NULL) {
1156 g_free(pref->saved_val.string);
1157 pref->saved_val.string = NULL;
1162 if (pref->saved_val.range != NULL) {
1163 g_free(pref->saved_val.range);
1164 pref->saved_val.range = NULL;
1169 g_assert_not_reached();
1176 module_prefs_clean(module_t *module, gpointer user_data _U_)
1178 /* For all preferences in this module, clean up any cruft allocated for
1179 use by the GUI code. */
1180 prefs_pref_foreach(module, pref_clean, NULL);
1181 return 0; /* keep cleaning modules */
1184 /* fetch all pref values from all pages */
1186 prefs_main_fetch_all(GtkWidget *dlg, gboolean *must_redissect)
1190 /* First, check that the values are all valid. */
1191 /* XXX - check the non-registered preferences too */
1192 switch (prefs_modules_foreach(module_prefs_check, (gpointer)&badpref)) {
1194 case PREFS_SET_SYNTAX_ERR:
1195 switch (badpref->type) {
1198 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1199 "The value for \"%s\" isn't a valid number.",
1204 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1205 "The value for \"%s\" isn't a valid range.",
1210 g_assert_not_reached();
1215 /* Fetch the preferences (i.e., make sure all the values set in all of
1216 the preferences panes have been copied to "prefs" and the registered
1218 gui_prefs_fetch(OBJECT_GET_DATA(dlg, E_GUI_PAGE_KEY));
1219 layout_prefs_fetch(OBJECT_GET_DATA(dlg, E_GUI_LAYOUT_PAGE_KEY));
1220 column_prefs_fetch(OBJECT_GET_DATA(dlg, E_GUI_COLUMN_PAGE_KEY));
1221 stream_prefs_fetch(OBJECT_GET_DATA(dlg, E_GUI_COLORS_PAGE_KEY));
1225 /* Is WPcap loaded? */
1228 capture_prefs_fetch(OBJECT_GET_DATA(dlg, E_CAPTURE_PAGE_KEY));
1232 #endif /* HAVE_LIBPCAP */
1233 printer_prefs_fetch(OBJECT_GET_DATA(dlg, E_PRINT_PAGE_KEY));
1234 nameres_prefs_fetch(OBJECT_GET_DATA(dlg, E_NAMERES_PAGE_KEY));
1236 prefs_modules_foreach(module_prefs_fetch, must_redissect);
1241 /* apply all pref values to the real world */
1243 prefs_main_apply_all(GtkWidget *dlg)
1248 * Apply the protocol preferences first - "gui_prefs_apply()" could
1249 * cause redissection, and we have to make sure the protocol
1250 * preference changes have been fully applied.
1254 gui_prefs_apply(OBJECT_GET_DATA(dlg, E_GUI_PAGE_KEY));
1255 layout_prefs_apply(OBJECT_GET_DATA(dlg, E_GUI_LAYOUT_PAGE_KEY));
1256 column_prefs_apply(OBJECT_GET_DATA(dlg, E_GUI_COLUMN_PAGE_KEY));
1257 stream_prefs_apply(OBJECT_GET_DATA(dlg, E_GUI_COLORS_PAGE_KEY));
1261 /* Is WPcap loaded? */
1264 capture_prefs_apply(OBJECT_GET_DATA(dlg, E_CAPTURE_PAGE_KEY));
1268 #endif /* HAVE_LIBPCAP */
1269 printer_prefs_apply(OBJECT_GET_DATA(dlg, E_PRINT_PAGE_KEY));
1270 nameres_prefs_apply(OBJECT_GET_DATA(dlg, E_NAMERES_PAGE_KEY));
1272 /* show/hide the Save button - depending on setting */
1273 save_bt = OBJECT_GET_DATA(prefs_w, E_PREFSW_SAVE_BT_KEY);
1274 if(prefs.gui_use_pref_save) {
1275 gtk_widget_show(save_bt);
1277 gtk_widget_hide(save_bt);
1282 /* destroy all preferences ressources from all pages */
1284 prefs_main_destroy_all(GtkWidget *dlg)
1286 #if GTK_MAJOR_VERSION >= 2
1291 (frame = gtk_notebook_get_nth_page(OBJECT_GET_DATA(prefs_w, E_PREFSW_NOTEBOOK_KEY), page_num)) != NULL;
1293 if(OBJECT_GET_DATA(frame, E_PAGE_ITER_KEY))
1294 gtk_tree_iter_free(OBJECT_GET_DATA(frame, E_PAGE_ITER_KEY));
1298 gui_prefs_destroy(OBJECT_GET_DATA(dlg, E_GUI_PAGE_KEY));
1299 layout_prefs_destroy(OBJECT_GET_DATA(dlg, E_GUI_LAYOUT_PAGE_KEY));
1300 column_prefs_destroy(OBJECT_GET_DATA(dlg, E_GUI_COLUMN_PAGE_KEY));
1301 stream_prefs_destroy(OBJECT_GET_DATA(dlg, E_GUI_COLORS_PAGE_KEY));
1305 /* Is WPcap loaded? */
1308 capture_prefs_destroy(OBJECT_GET_DATA(dlg, E_CAPTURE_PAGE_KEY));
1312 #endif /* HAVE_LIBPCAP */
1313 printer_prefs_destroy(OBJECT_GET_DATA(dlg, E_PRINT_PAGE_KEY));
1314 nameres_prefs_destroy(OBJECT_GET_DATA(dlg, E_NAMERES_PAGE_KEY));
1316 /* Free up the saved preferences (both for "prefs" and for registered
1318 free_prefs(&saved_prefs);
1319 prefs_modules_foreach(module_prefs_clean, NULL);
1324 prefs_main_write(void)
1330 /* Create the directory that holds personal configuration files, if
1332 if (create_persconffile_dir(&pf_dir_path) == -1) {
1333 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1334 "Can't create directory\n\"%s\"\nfor preferences file: %s.", pf_dir_path,
1336 g_free(pf_dir_path);
1338 /* Write the preferencs out. */
1339 err = write_prefs(&pf_path);
1341 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1342 "Can't open preferences file\n\"%s\": %s.", pf_path,
1350 * Load the Wireshark decryption keys (just set) and save
1351 * the changes to the adapters' registry
1353 airpcap_load_decryption_keys(airpcap_if_list);
1359 prefs_main_ok_cb(GtkWidget *ok_bt _U_, gpointer parent_w)
1361 gboolean must_redissect = FALSE;
1363 if (!prefs_main_fetch_all(parent_w, &must_redissect))
1364 return; /* Errors in some preference setting - already reported */
1366 /* if we don't have a Save button, just save the settings now */
1367 if (!prefs.gui_use_pref_save) {
1371 prefs_main_apply_all(parent_w);
1373 /* Fill in capture options with values from the preferences */
1374 prefs_to_capture_opts();
1377 prefs_airpcap_update();
1380 /* Now destroy the "Preferences" dialog. */
1381 window_destroy(GTK_WIDGET(parent_w));
1383 if (must_redissect) {
1384 /* Redissect all the packets, and re-evaluate the display filter. */
1385 cf_redissect_packets(&cfile);
1391 prefs_main_apply_cb(GtkWidget *apply_bt _U_, gpointer parent_w)
1393 gboolean must_redissect = FALSE;
1395 if (!prefs_main_fetch_all(parent_w, &must_redissect))
1396 return; /* Errors in some preference setting - already reported */
1398 /* if we don't have a Save button, just save the settings now */
1399 if (!prefs.gui_use_pref_save) {
1403 prefs_main_apply_all(parent_w);
1405 /* Fill in capture options with values from the preferences */
1406 prefs_to_capture_opts();
1409 prefs_airpcap_update();
1412 if (must_redissect) {
1413 /* Redissect all the packets, and re-evaluate the display filter. */
1414 cf_redissect_packets(&cfile);
1419 prefs_main_save_cb(GtkWidget *save_bt _U_, gpointer parent_w)
1421 gboolean must_redissect = FALSE;
1423 if (!prefs_main_fetch_all(parent_w, &must_redissect))
1424 return; /* Errors in some preference setting - already reported */
1428 /* Now apply those preferences.
1429 XXX - should we do this? The user didn't click "OK" or "Apply".
1432 1) by saving the preferences they presumably indicate that they
1435 2) the next time they fire Wireshark up, those preferences will
1438 3) we'd have to buffer "must_redissect" so that if they do
1439 "Apply" after this, we know we have to redissect;
1441 4) we did apply the protocol preferences, at least, in the past. */
1442 prefs_main_apply_all(parent_w);
1444 /* Fill in capture options with values from the preferences */
1445 prefs_to_capture_opts();
1447 if (must_redissect) {
1448 /* Redissect all the packets, and re-evaluate the display filter. */
1449 cf_redissect_packets(&cfile);
1454 pref_revert(pref_t *pref, gpointer user_data)
1456 gboolean *pref_changed_p = user_data;
1458 /* Revert the preference to its saved value. */
1459 switch (pref->type) {
1462 if (*pref->varp.uint != pref->saved_val.uint) {
1463 *pref_changed_p = TRUE;
1464 *pref->varp.uint = pref->saved_val.uint;
1469 if (*pref->varp.boolp != pref->saved_val.boolval) {
1470 *pref_changed_p = TRUE;
1471 *pref->varp.boolp = pref->saved_val.boolval;
1476 if (*pref->varp.enump != pref->saved_val.enumval) {
1477 *pref_changed_p = TRUE;
1478 *pref->varp.enump = pref->saved_val.enumval;
1483 if (strcmp(*pref->varp.string, pref->saved_val.string) != 0) {
1484 *pref_changed_p = TRUE;
1485 g_free((void *)*pref->varp.string);
1486 *pref->varp.string = g_strdup(pref->saved_val.string);
1491 if (!ranges_are_equal(*pref->varp.range, pref->saved_val.range)) {
1492 *pref_changed_p = TRUE;
1493 g_free(*pref->varp.range);
1494 *pref->varp.range = range_copy(pref->saved_val.range);
1499 g_assert_not_reached();
1506 module_prefs_revert(module_t *module, gpointer user_data)
1508 gboolean *must_redissect_p = user_data;
1510 /* For all preferences in this module, revert its value to the value
1511 it had when we popped up the Preferences dialog. Find out whether
1512 this changes any of them. */
1513 module->prefs_changed = FALSE; /* assume none of them changed */
1514 prefs_pref_foreach(module, pref_revert, &module->prefs_changed);
1516 /* If any of them changed, indicate that we must redissect and refilter
1517 the current capture (if we have one), as the preference change
1518 could cause packets to be dissected differently. */
1519 if (module->prefs_changed)
1520 *must_redissect_p = TRUE;
1521 return 0; /* keep processing modules */
1524 /* cancel button pressed, revert prefs to saved and exit dialog */
1526 prefs_main_cancel_cb(GtkWidget *cancel_bt _U_, gpointer parent_w)
1528 gboolean must_redissect = FALSE;
1530 /* Free up the current preferences and copy the saved preferences to the
1531 current preferences. */
1533 copy_prefs(&prefs, &saved_prefs);
1535 /* Now revert the registered preferences. */
1536 prefs_modules_foreach(module_prefs_revert, &must_redissect);
1538 /* Now apply the reverted-to preferences. */
1539 prefs_main_apply_all(parent_w);
1541 window_destroy(GTK_WIDGET(parent_w));
1543 if (must_redissect) {
1544 /* Redissect all the packets, and re-evaluate the display filter. */
1545 cf_redissect_packets(&cfile);
1549 /* Treat this as a cancel, by calling "prefs_main_cancel_cb()" */
1551 prefs_main_delete_event_cb(GtkWidget *prefs_w, GdkEvent *event _U_,
1552 gpointer parent_w _U_)
1554 prefs_main_cancel_cb(NULL, prefs_w);
1559 /* dialog *is* already destroyed, clean up memory and such */
1561 prefs_main_destroy_cb(GtkWidget *win _U_, gpointer parent_w)
1563 prefs_main_destroy_all(parent_w);
1565 /* Note that we no longer have a "Preferences" dialog box. */
1569 struct properties_data {
1575 module_search_properties(module_t *module, gpointer user_data)
1577 struct properties_data *p = (struct properties_data *)user_data;
1579 /* If this module has the specified title, remember it. */
1580 if (strcmp(module->title, p->title) == 0) {
1582 return 1; /* stops the search */
1588 /* select a node in the tree view */
1589 /* XXX - this is almost 100% copied from byte_view_select() in proto_draw.c,
1590 * find a way to combine both to have a generic function for this */
1592 tree_select_node(GtkWidget *tree, prefs_tree_iter *iter)
1594 #if GTK_MAJOR_VERSION < 2
1595 GtkCTree *ctree = GTK_CTREE(tree);
1596 GtkCTreeNode *node = (GtkCTreeNode *) iter;
1597 GtkCTreeNode *parent;
1599 GtkTreeIter local_iter = *iter;
1600 GtkTreeView *tree_view = GTK_TREE_VIEW(tree);
1601 GtkTreeModel *model;
1602 GtkTreePath *first_path, *path;
1606 #if GTK_MAJOR_VERSION < 2
1607 /* Expand and select our field's row */
1608 gtk_ctree_expand(ctree, node);
1609 gtk_ctree_select(ctree, node);
1610 /*expand_tree(ctree, node, NULL);*/
1612 /* ... and its parents */
1613 parent = GTK_CTREE_ROW(node)->parent;
1615 gtk_ctree_expand(ctree, parent);
1616 /*expand_tree(ctree, parent, NULL);*/
1617 parent = GTK_CTREE_ROW(parent)->parent;
1620 /* And position the window so the selection is visible.
1621 * Position the selection in the middle of the viewable
1623 gtk_ctree_node_moveto(ctree, node, 0, .5, 0);
1625 model = gtk_tree_view_get_model(tree_view);
1627 /* Expand our field's row */
1628 first_path = gtk_tree_model_get_path(model, &local_iter);
1629 gtk_tree_view_expand_row(tree_view, first_path, FALSE);
1630 /*expand_tree(tree_view, &iter, NULL, NULL);*/
1632 /* ... and its parents */
1633 while (gtk_tree_model_iter_parent(model, &parent, &local_iter)) {
1634 path = gtk_tree_model_get_path(model, &parent);
1635 gtk_tree_view_expand_row(tree_view, path, FALSE);
1636 /*expand_tree(tree_view, &parent, NULL, NULL);*/
1637 local_iter = parent;
1638 gtk_tree_path_free(path);
1641 /* select our field's row */
1642 gtk_tree_selection_select_path(gtk_tree_view_get_selection(tree_view),
1645 /* And position the window so the selection is visible.
1646 * Position the selection in the middle of the viewable
1648 gtk_tree_view_scroll_to_cell(tree_view, first_path, NULL, TRUE, 0.5, 0.0);
1650 gtk_tree_path_free(first_path);
1655 /* search the corresponding protocol page of the currently selected field */
1657 properties_cb(GtkWidget *w, gpointer dummy)
1659 header_field_info *hfinfo;
1661 struct properties_data p;
1665 module_t *page_module;
1667 if (cfile.finfo_selected == NULL) {
1668 /* There is no field selected */
1672 /* Find the title for the protocol for the selected field. */
1673 hfinfo = cfile.finfo_selected->hfinfo;
1674 if (hfinfo->parent == -1)
1675 title = prefs_get_title_by_name(hfinfo->abbrev);
1677 title = prefs_get_title_by_name(proto_registrar_get_abbrev(hfinfo->parent));
1679 return; /* Couldn't find it. XXX - just crash? "Can't happen"? */
1681 /* Find the module for that protocol by searching for one with that title.
1682 XXX - should we just associate protocols with modules directly? */
1685 prefs_module_list_foreach(protocols_module->prefs, module_search_properties,
1687 if (p.module == NULL) {
1688 /* We didn't find it - that protocol probably has no preferences. */
1692 /* Create a preferences window, or pop up an existing one. */
1693 if (prefs_w != NULL) {
1694 reactivate_window(prefs_w);
1699 /* Search all the pages in that window for the one with the specified
1702 (sw = gtk_notebook_get_nth_page(OBJECT_GET_DATA(prefs_w, E_PREFSW_NOTEBOOK_KEY), page_num)) != NULL;
1704 /* Get the frame from the scrollable window */
1705 frame = OBJECT_GET_DATA(sw, E_PAGESW_FRAME_KEY);
1706 /* Get the module for this page. */
1707 page_module = OBJECT_GET_DATA(frame, E_PAGE_MODULE_KEY);
1708 if (page_module == NULL)
1709 continue; /* It doesn't have one. */
1710 if (page_module == p.module) {
1712 OBJECT_GET_DATA(prefs_w, E_PREFSW_TREE_KEY),
1713 OBJECT_GET_DATA(frame, E_PAGE_ITER_KEY));
1719 /* Prefs tree selection callback. The node data has been loaded with
1720 the proper notebook page to load. */
1721 #if GTK_MAJOR_VERSION < 2
1723 prefs_tree_select_cb(GtkCTree *ct, GtkCTreeNode *node, gint col _U_,
1727 prefs_tree_select_cb(GtkTreeSelection *sel, gpointer dummy _U_)
1731 #if GTK_MAJOR_VERSION >= 2
1732 GtkTreeModel *model;
1736 #if GTK_MAJOR_VERSION < 2
1737 page = GPOINTER_TO_INT(gtk_ctree_node_get_row_data(ct, node));
1740 gtk_notebook_set_page(OBJECT_GET_DATA(prefs_w, E_PREFSW_NOTEBOOK_KEY), page);
1742 if (gtk_tree_selection_get_selected(sel, &model, &iter))
1744 gtk_tree_model_get(model, &iter, 1, &page, -1);
1746 gtk_notebook_set_page(OBJECT_GET_DATA(prefs_w, E_PREFSW_NOTEBOOK_KEY), page);