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>
34 #include <epan/packet.h>
35 #include <epan/prefs.h>
36 #include <epan/strutil.h>
37 #include <epan/prefs-int.h>
41 #include "../simple_dialog.h"
44 #include "gtk/prefs_column.h"
45 #include "gtk/prefs_dlg.h"
46 #include "gtk/prefs_print.h"
47 #include "gtk/prefs_stream.h"
48 #include "gtk/prefs_gui.h"
49 #include "gtk/prefs_layout.h"
50 #include "gtk/prefs_capture.h"
51 #include "gtk/prefs_nameres.h"
52 #include "gtk/prefs_taps.h"
53 #include "gtk/prefs_protocols.h"
54 #include "gtk/gui_utils.h"
55 #include "gtk/dlg_utils.h"
56 #include "gtk/stock_icons.h"
57 #include "gtk/help_dlg.h"
59 #include "gtk/uat_gui.h"
64 #include "capture-wpcap.h"
68 #include "airpcap_loader.h"
69 #include "airpcap_gui_utils.h"
74 static void prefs_main_ok_cb(GtkWidget *, gpointer);
75 static void prefs_main_apply_cb(GtkWidget *, gpointer);
76 static void prefs_main_save_cb(GtkWidget *, gpointer);
77 static void prefs_main_cancel_cb(GtkWidget *, gpointer);
78 static gboolean prefs_main_delete_event_cb(GtkWidget *, GdkEvent *, gpointer);
79 static void prefs_main_destroy_cb(GtkWidget *, gpointer);
80 static void prefs_tree_select_cb(GtkTreeSelection *, gpointer);
83 #define E_PREFSW_SCROLLW_KEY "prefsw_scrollw"
84 #define E_PREFSW_TREE_KEY "prefsw_tree"
85 #define E_PREFSW_NOTEBOOK_KEY "prefsw_notebook"
86 #define E_PREFSW_SAVE_BT_KEY "prefsw_save_bt"
87 #define E_PAGE_ITER_KEY "page_iter"
88 #define E_PAGE_MODULE_KEY "page_module"
89 #define E_PAGESW_FRAME_KEY "pagesw_frame"
91 #define E_GUI_PAGE_KEY "gui_options_page"
92 #define E_GUI_LAYOUT_PAGE_KEY "gui_layout_page"
93 #define E_GUI_COLUMN_PAGE_KEY "gui_column_options_page"
94 #define E_GUI_FONT_PAGE_KEY "gui_font_options_page"
95 #define E_GUI_COLORS_PAGE_KEY "gui_colors_options_page"
96 #define E_CAPTURE_PAGE_KEY "capture_options_page"
97 #define E_PRINT_PAGE_KEY "printer_options_page"
98 #define E_NAMERES_PAGE_KEY "nameres_options_page"
99 #define E_TAPS_PAGE_KEY "taps_options_page"
100 #define E_PROTOCOLS_PAGE_KEY "protocols_options_page"
103 * Keep a static pointer to the current "Preferences" window, if any, so that
104 * if somebody tries to do "Edit:Preferences" while there's already a
105 * "Preferences" window up, we just pop up the existing one, rather than
106 * creating a new one.
108 static GtkWidget *prefs_w;
111 * Save the value of the preferences as of when the preferences dialog
112 * box was first popped up, so we can revert to those values if the
113 * user selects "Cancel".
115 static e_prefs saved_prefs;
122 GtkTooltips *tooltips;
124 gboolean is_protocol;
127 static gint protocols_page = 0;
130 pref_exists(pref_t *pref _U_, gpointer user_data _U_)
135 /* show a single preference on the GtkTable of a preference page */
137 pref_show(pref_t *pref, gpointer user_data)
139 GtkWidget *main_tb = user_data;
145 /* Give this preference a label which is its title, followed by a colon,
146 and left-align it. */
148 label_len = strlen(title) + 2;
149 label_string = g_malloc(label_len);
150 g_strlcpy(label_string, title, label_len);
153 * Sometimes we don't want to append a ':' after a static text string...
154 * If it is needed, we will specify it in the string itself.
156 if(pref->type != PREF_STATIC_TEXT)
157 g_strlcat(label_string, ":", label_len);
159 /* Save the current value of the preference, so that we can revert it if
160 the user does "Apply" and then "Cancel", and create the control for
161 editing the preference. */
162 switch (pref->type) {
165 pref->saved_val.uint = *pref->varp.uint;
167 /* XXX - there are no uint spinbuttons, so we can't use a spinbutton.
168 Even more annoyingly, even if there were, GLib doesn't define
169 G_MAXUINT - but I think ANSI C may define UINT_MAX, so we could
171 switch (pref->info.base) {
174 g_snprintf(uint_str, sizeof(uint_str), "%u", pref->saved_val.uint);
178 g_snprintf(uint_str, sizeof(uint_str), "%o", pref->saved_val.uint);
182 g_snprintf(uint_str, sizeof(uint_str), "%x", pref->saved_val.uint);
185 pref->control = create_preference_entry(main_tb, pref->ordinal,
186 label_string, pref->description,
191 pref->saved_val.boolval = *pref->varp.boolp;
192 pref->control = create_preference_check_button(main_tb, pref->ordinal,
193 label_string, pref->description,
194 pref->saved_val.boolval);
198 pref->saved_val.enumval = *pref->varp.enump;
199 if (pref->info.enum_info.radio_buttons) {
200 /* Show it as radio buttons. */
201 pref->control = create_preference_radio_buttons(main_tb, pref->ordinal,
202 label_string, pref->description,
203 pref->info.enum_info.enumvals,
204 pref->saved_val.enumval);
206 /* Show it as an option menu. */
207 pref->control = create_preference_option_menu(main_tb, pref->ordinal,
208 label_string, pref->description,
209 pref->info.enum_info.enumvals,
210 pref->saved_val.enumval);
215 g_free(pref->saved_val.string);
216 pref->saved_val.string = g_strdup(*pref->varp.string);
217 pref->control = create_preference_entry(main_tb, pref->ordinal,
218 label_string, pref->description,
219 pref->saved_val.string);
226 g_free(pref->saved_val.range);
227 pref->saved_val.range = range_copy(*pref->varp.range);
228 range_string = range_convert_range(*pref->varp.range);
229 pref->control = create_preference_entry(main_tb, pref->ordinal,
230 label_string, pref->description,
235 case PREF_STATIC_TEXT:
237 pref->control = create_preference_static_text(main_tb, pref->ordinal,
238 label_string, pref->description);
244 pref->control = create_preference_uat(main_tb, pref->ordinal,
245 label_string, pref->description,
251 g_assert_not_reached();
254 g_free(label_string);
259 #define MAX_TREE_NODE_NAME_LEN 64
260 /* show prefs page for each registered module (protocol) */
262 module_prefs_show(module_t *module, gpointer user_data)
264 struct ct_struct *cts = user_data;
265 struct ct_struct child_cts;
266 GtkWidget *main_vb, *main_tb, *frame, *main_sw;
267 gchar label_str[MAX_TREE_NODE_NAME_LEN];
272 * Is this module a subtree, with modules underneath it?
274 if (!prefs_module_has_submodules(module)) {
277 * Does it have any preferences (other than possibly obsolete ones)?
279 if (prefs_pref_foreach(module, pref_exists, NULL) == 0) {
281 * No. Don't put the module into the preferences window.
282 * XXX - we should do the same for subtrees; if a subtree has
283 * nothing under it that will be displayed, don't put it into
291 * Add this module to the tree.
293 g_strlcpy(label_str, module->title, MAX_TREE_NODE_NAME_LEN);
294 model = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(cts->tree)));
295 if (prefs_module_has_submodules(module) && !cts->iter.stamp)
296 gtk_tree_store_append(model, &iter, NULL);
298 gtk_tree_store_append(model, &iter, &cts->iter);
303 if (prefs_module_has_submodules(module)) {
308 gtk_tree_store_set(model, &iter, 0, label_str, 1, -1, -1);
311 * Walk the subtree and attach stuff to it.
314 child_cts.iter = iter;
315 if (module == protocols_module)
316 child_cts.is_protocol = TRUE;
317 prefs_modules_foreach_submodules(module, module_prefs_show, &child_cts);
319 /* keep the page count right */
320 cts->page = child_cts.page;
325 * Has preferences. Create a notebook page for it.
328 /* Scrolled window */
329 main_sw = gtk_scrolled_window_new(NULL, NULL);
330 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(main_sw), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
333 frame = gtk_frame_new(module->description);
334 gtk_container_set_border_width(GTK_CONTAINER(frame), 5);
335 gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(main_sw), frame);
336 g_object_set_data(G_OBJECT(main_sw), E_PAGESW_FRAME_KEY, frame);
338 /* Main vertical box */
339 main_vb = gtk_vbox_new(FALSE, 5);
340 gtk_container_set_border_width(GTK_CONTAINER(main_vb), 5);
341 gtk_container_add(GTK_CONTAINER(frame), main_vb);
344 main_tb = gtk_table_new(module->numprefs, 2, FALSE);
345 gtk_box_pack_start(GTK_BOX(main_vb), main_tb, FALSE, FALSE, 0);
346 gtk_table_set_row_spacings(GTK_TABLE(main_tb), 10);
347 gtk_table_set_col_spacings(GTK_TABLE(main_tb), 15);
348 g_object_set_data(G_OBJECT(main_tb), E_TOOLTIPS_KEY, cts->tooltips);
350 /* Add items for each of the preferences */
351 prefs_pref_foreach(module, pref_show, main_tb);
353 /* Associate this module with the page's frame. */
354 g_object_set_data(G_OBJECT(frame), E_PAGE_MODULE_KEY, module);
356 /* Add the page to the notebook */
357 gtk_notebook_append_page(GTK_NOTEBOOK(cts->notebook), main_sw, NULL);
359 /* Attach the page to the tree item */
360 gtk_tree_store_set(model, &iter, 0, label_str, 1, cts->page, -1);
361 g_object_set_data(G_OBJECT(frame), E_PAGE_ITER_KEY, gtk_tree_iter_copy(&iter));
365 /* Show 'em what we got */
366 gtk_widget_show_all(main_sw);
368 /* show the protocols page */
370 gtk_tree_store_set(model, &iter, 0, label_str, 1, protocols_page, -1);
378 #define prefs_tree_iter GtkTreeIter
380 /* add a page to the tree */
381 static prefs_tree_iter
382 prefs_tree_page_add(const gchar *title, gint page_nr,
383 gpointer store, prefs_tree_iter *parent_iter)
385 prefs_tree_iter iter;
387 gtk_tree_store_append(store, &iter, parent_iter);
388 gtk_tree_store_set(store, &iter, 0, title, 1, page_nr, -1);
392 /* add a page to the notebook */
394 prefs_nb_page_add(GtkWidget *notebook, const gchar *title, GtkWidget *page, const char *page_key)
398 frame = gtk_frame_new(title);
399 gtk_widget_show(frame);
401 gtk_container_add(GTK_CONTAINER(frame), page);
402 g_object_set_data(G_OBJECT(prefs_w), page_key, page);
404 gtk_notebook_append_page (GTK_NOTEBOOK(notebook), frame, NULL);
410 /* show the dialog */
412 prefs_cb(GtkWidget *w _U_, gpointer dummy _U_)
414 GtkWidget *top_hb, *bbox, *prefs_nb, *ct_sb,
415 *ok_bt, *apply_bt, *save_bt, *cancel_bt, *help_bt;
416 GtkWidget *gui_font_pg;
417 gchar label_str[MAX_TREE_NODE_NAME_LEN];
418 struct ct_struct cts;
420 GtkTreeSelection *selection;
421 GtkCellRenderer *renderer;
422 GtkTreeViewColumn *column;
424 prefs_tree_iter gui_iter;
427 if (prefs_w != NULL) {
428 /* There's already a "Preferences" dialog box; reactivate it. */
429 reactivate_window(prefs_w);
433 /* Save the current preferences, so we can revert to those values
434 if the user presses "Cancel". */
435 copy_prefs(&saved_prefs, &prefs);
437 prefs_w = dlg_conf_window_new("Wireshark: Preferences");
440 * Unfortunately, we can't arrange that a GtkTable widget wrap an event box
441 * around a table row, so the spacing between the preference item's label
442 * and its control widgets is inactive and the tooltip doesn't pop up when
443 * the mouse is over it.
445 cts.tooltips = gtk_tooltips_new();
447 /* Container for each row of widgets */
448 cts.main_vb = gtk_vbox_new(FALSE, 5);
449 gtk_container_set_border_width(GTK_CONTAINER(cts.main_vb), 5);
450 gtk_container_add(GTK_CONTAINER(prefs_w), cts.main_vb);
451 gtk_widget_show(cts.main_vb);
453 /* Top row: Preferences tree and notebook */
454 top_hb = gtk_hbox_new(FALSE, 10);
455 gtk_container_add(GTK_CONTAINER(cts.main_vb), top_hb);
456 gtk_widget_show(top_hb);
458 /* scrolled window on the left for the categories tree */
459 ct_sb = scrolled_window_new(NULL, NULL);
460 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(ct_sb),
462 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(ct_sb),
463 GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
464 gtk_container_add(GTK_CONTAINER(top_hb), ct_sb);
465 gtk_widget_show(ct_sb);
466 g_object_set_data(G_OBJECT(prefs_w), E_PREFSW_SCROLLW_KEY, ct_sb);
468 /* categories tree */
469 store = gtk_tree_store_new(2, G_TYPE_STRING, G_TYPE_INT);
470 cts.tree = tree_view_new(GTK_TREE_MODEL(store));
471 cts.iter.stamp = 0; /* mark this as the toplevel */
472 g_object_set_data(G_OBJECT(prefs_w), E_PREFSW_TREE_KEY, cts.tree);
473 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(cts.tree), FALSE);
474 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(cts.tree));
475 gtk_tree_selection_set_mode(selection, GTK_SELECTION_SINGLE);
476 renderer = gtk_cell_renderer_text_new();
477 col_offset = gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(cts.tree),
478 -1, "Name", renderer,
480 column = gtk_tree_view_get_column(GTK_TREE_VIEW(cts.tree),
482 gtk_tree_view_column_set_sizing(GTK_TREE_VIEW_COLUMN(column),
483 GTK_TREE_VIEW_COLUMN_AUTOSIZE);
484 g_signal_connect(selection, "changed", G_CALLBACK(prefs_tree_select_cb), NULL);
485 gtk_container_add(GTK_CONTAINER(ct_sb), cts.tree);
486 gtk_widget_show(cts.tree);
488 /* A notebook widget without tabs is used to flip between prefs */
489 prefs_nb = gtk_notebook_new();
490 g_object_set_data(G_OBJECT(prefs_w), E_PREFSW_NOTEBOOK_KEY, prefs_nb);
491 gtk_notebook_set_show_tabs(GTK_NOTEBOOK(prefs_nb), FALSE);
492 gtk_notebook_set_show_border(GTK_NOTEBOOK(prefs_nb), FALSE);
493 gtk_container_add(GTK_CONTAINER(top_hb), prefs_nb);
494 gtk_widget_show(prefs_nb);
498 /* Preferences common for all protocols */
499 g_strlcpy(label_str, "Protocols", MAX_TREE_NODE_NAME_LEN);
500 prefs_nb_page_add(prefs_nb, label_str, protocols_prefs_show(), E_PROTOCOLS_PAGE_KEY);
501 protocols_page = cts.page++;
504 g_strlcpy(label_str, "User Interface", MAX_TREE_NODE_NAME_LEN);
505 prefs_nb_page_add(prefs_nb, label_str, gui_prefs_show(), E_GUI_PAGE_KEY);
506 gui_iter = prefs_tree_page_add(label_str, cts.page, store, NULL);
509 /* GUI layout prefs */
510 g_strlcpy(label_str, "Layout", MAX_TREE_NODE_NAME_LEN);
511 prefs_nb_page_add(prefs_nb, label_str, layout_prefs_show(), E_GUI_LAYOUT_PAGE_KEY);
512 prefs_tree_page_add(label_str, cts.page, store, &gui_iter);
515 /* GUI Column prefs */
516 g_strlcpy(label_str, "Columns", MAX_TREE_NODE_NAME_LEN);
517 prefs_nb_page_add(prefs_nb, label_str, column_prefs_show(prefs_w), E_GUI_COLUMN_PAGE_KEY);
518 prefs_tree_page_add(label_str, cts.page, store, &gui_iter);
522 g_strlcpy(label_str, "Font", MAX_TREE_NODE_NAME_LEN);
523 gui_font_pg = gui_font_prefs_show();
524 prefs_nb_page_add(prefs_nb, label_str, gui_font_pg, E_GUI_FONT_PAGE_KEY);
525 prefs_tree_page_add(label_str, cts.page, store, &gui_iter);
528 gtk_container_set_border_width( GTK_CONTAINER(gui_font_pg), 5 );
530 /* IMPORTANT: the following gtk_font_selection_set_font_name() function will
531 only work if the widget and it's corresponding window is already shown
532 (so don't put the following into gui_font_prefs_show()) !!! */
534 /* We set the current font now, because setting it appears not to work
535 when run before appending the frame to the notebook. */
537 gtk_font_selection_set_font_name(
538 GTK_FONT_SELECTION(gui_font_pg), prefs.gui_font_name);
540 /* GUI Colors prefs */
541 g_strlcpy(label_str, "Colors", MAX_TREE_NODE_NAME_LEN);
542 prefs_nb_page_add(prefs_nb, label_str, stream_prefs_show(), E_GUI_COLORS_PAGE_KEY);
543 prefs_tree_page_add(label_str, cts.page, store, &gui_iter);
546 /* select the main GUI page as the default page and expand it's children */
547 gtk_tree_selection_select_iter(selection, &gui_iter);
548 /* (expand will only take effect, when at least one child exists) */
549 gtk_tree_view_expand_all(GTK_TREE_VIEW(cts.tree));
553 /* Is WPcap loaded? */
557 g_strlcpy(label_str, "Capture", MAX_TREE_NODE_NAME_LEN);
558 prefs_nb_page_add(prefs_nb, label_str, capture_prefs_show(), E_CAPTURE_PAGE_KEY);
559 prefs_tree_page_add(label_str, cts.page, store, NULL);
564 #endif /* HAVE_LIBPCAP */
567 g_strlcpy(label_str, "Printing", MAX_TREE_NODE_NAME_LEN);
568 prefs_nb_page_add(prefs_nb, label_str, printer_prefs_show(), E_PRINT_PAGE_KEY);
569 prefs_tree_page_add(label_str, cts.page, store, NULL);
572 /* Name resolution prefs */
573 g_strlcpy(label_str, "Name Resolution", MAX_TREE_NODE_NAME_LEN);
574 prefs_nb_page_add(prefs_nb, label_str, nameres_prefs_show(), E_NAMERES_PAGE_KEY);
575 prefs_tree_page_add(label_str, cts.page, store, NULL);
578 /* TAPS player prefs */
579 g_strlcpy(label_str, "Statistics", MAX_TREE_NODE_NAME_LEN);
580 prefs_nb_page_add(prefs_nb, label_str, stats_prefs_show(), E_TAPS_PAGE_KEY);
581 prefs_tree_page_add(label_str, cts.page, store, NULL);
584 /* Registered prefs */
585 cts.notebook = prefs_nb;
586 cts.is_protocol = FALSE;
587 prefs_modules_foreach_submodules(NULL, module_prefs_show, &cts);
589 /* Button row: OK and alike buttons */
590 bbox = dlg_button_row_new(GTK_STOCK_HELP, GTK_STOCK_OK, GTK_STOCK_APPLY, GTK_STOCK_SAVE, GTK_STOCK_CANCEL, NULL);
591 gtk_box_pack_start(GTK_BOX(cts.main_vb), bbox, FALSE, FALSE, 0);
592 gtk_widget_show(bbox);
594 ok_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_OK);
595 g_signal_connect(ok_bt, "clicked", G_CALLBACK(prefs_main_ok_cb), prefs_w);
597 apply_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_APPLY);
598 g_signal_connect(apply_bt, "clicked", G_CALLBACK(prefs_main_apply_cb), prefs_w);
600 save_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_SAVE);
601 g_signal_connect(save_bt, "clicked", G_CALLBACK(prefs_main_save_cb), prefs_w);
602 g_object_set_data(G_OBJECT(prefs_w), E_PREFSW_SAVE_BT_KEY, save_bt);
604 cancel_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_CANCEL);
605 g_signal_connect(cancel_bt, "clicked", G_CALLBACK(prefs_main_cancel_cb), prefs_w);
606 window_set_cancel_button(prefs_w, cancel_bt, NULL);
608 gtk_widget_grab_default(ok_bt);
610 help_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_HELP);
611 g_signal_connect(help_bt, "clicked", G_CALLBACK(topic_cb), (gpointer)HELP_PREFERENCES_DIALOG);
613 g_signal_connect(prefs_w, "delete_event", G_CALLBACK(prefs_main_delete_event_cb), prefs_w);
614 g_signal_connect(prefs_w, "destroy", G_CALLBACK(prefs_main_destroy_cb), prefs_w);
616 gtk_widget_show(prefs_w);
618 /* hide the Save button if the user uses implicit save */
619 if(!prefs.gui_use_pref_save) {
620 gtk_widget_hide(save_bt);
623 window_present(prefs_w);
625 g_object_unref(G_OBJECT(store));
629 set_option_label(GtkWidget *main_tb, int table_position,
630 const gchar *label_text, const gchar *tooltip_text, GtkTooltips *tooltips)
633 GtkWidget *event_box;
635 label = gtk_label_new(label_text);
636 gtk_misc_set_alignment(GTK_MISC(label), 1.0, 0.5);
637 gtk_widget_show(label);
639 event_box = gtk_event_box_new();
640 gtk_event_box_set_visible_window (GTK_EVENT_BOX(event_box), FALSE);
641 gtk_table_attach_defaults(GTK_TABLE(main_tb), event_box, 0, 1,
642 table_position, table_position + 1);
643 if (tooltip_text != NULL && tooltips != NULL)
644 gtk_tooltips_set_tip(tooltips, event_box, tooltip_text, NULL);
645 gtk_container_add(GTK_CONTAINER(event_box), label);
646 gtk_widget_show(event_box);
650 create_preference_check_button(GtkWidget *main_tb, int table_position,
651 const gchar *label_text, const gchar *tooltip_text, gboolean active)
653 GtkTooltips *tooltips;
654 GtkWidget *check_box;
656 tooltips = g_object_get_data(G_OBJECT(main_tb), E_TOOLTIPS_KEY);
658 set_option_label(main_tb, table_position, label_text, tooltip_text,
661 check_box = gtk_check_button_new();
662 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check_box), active);
663 gtk_table_attach_defaults(GTK_TABLE(main_tb), check_box, 1, 2,
664 table_position, table_position + 1);
665 if (tooltip_text != NULL && tooltips != NULL)
666 gtk_tooltips_set_tip(tooltips, check_box, tooltip_text, NULL);
672 create_preference_radio_buttons(GtkWidget *main_tb, int table_position,
673 const gchar *label_text, const gchar *tooltip_text,
674 const enum_val_t *enumvals, gint current_val)
676 GtkTooltips *tooltips;
677 GtkWidget *radio_button_hbox, *button = NULL;
680 const enum_val_t *enum_valp;
681 GtkWidget *event_box;
683 tooltips = g_object_get_data(G_OBJECT(main_tb), E_TOOLTIPS_KEY);
685 set_option_label(main_tb, table_position, label_text, tooltip_text,
688 radio_button_hbox = gtk_hbox_new(FALSE, 0);
690 for (enum_valp = enumvals, index = 0; enum_valp->name != NULL;
691 enum_valp++, index++) {
692 button = gtk_radio_button_new_with_label(rb_group,
693 enum_valp->description);
694 gtk_widget_show(button);
695 rb_group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(button));
696 gtk_box_pack_start(GTK_BOX(radio_button_hbox), button, FALSE,
698 if (enum_valp->value == current_val) {
699 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button),
703 gtk_widget_show(radio_button_hbox);
705 event_box = gtk_event_box_new();
706 gtk_event_box_set_visible_window (GTK_EVENT_BOX(event_box), FALSE);
707 gtk_container_add(GTK_CONTAINER(event_box), radio_button_hbox);
708 gtk_table_attach_defaults(GTK_TABLE(main_tb), event_box, 1, 2,
709 table_position, table_position+1);
710 if (tooltip_text != NULL && tooltips != NULL)
711 gtk_tooltips_set_tip(tooltips, event_box, tooltip_text, NULL);
712 gtk_widget_show(event_box);
715 * It doesn't matter which of the buttons we return - we fetch
716 * the value by looking at the entire radio button group to
717 * which it belongs, and we can get that from any button.
723 label_to_enum_val(GtkWidget *label, const enum_val_t *enumvals)
728 /* Get the label's text, and translate it to a value.
729 We match only the descriptions, as those are what appear in
730 the option menu items or as labels for radio buttons.
731 We fail if we don't find a match, as that "can't happen". */
732 gtk_label_get(GTK_LABEL(label), &label_string);
734 for (i = 0; enumvals[i].name != NULL; i++) {
735 if (g_ascii_strcasecmp(label_string, enumvals[i].description) == 0) {
736 return enumvals[i].value;
739 g_assert_not_reached();
744 fetch_preference_radio_buttons_val(GtkWidget *button,
745 const enum_val_t *enumvals)
751 * Go through the list of of radio buttons in the button's group,
752 * and find the first one that's active.
754 rb_group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(button));
756 for (rb_entry = rb_group; rb_entry != NULL;
757 rb_entry = g_slist_next(rb_entry)) {
758 button = rb_entry->data;
759 if (GTK_TOGGLE_BUTTON(button)->active)
763 /* OK, now return the value corresponding to that button's label. */
764 return label_to_enum_val(GTK_BIN(button)->child, enumvals);
768 create_preference_option_menu(GtkWidget *main_tb, int table_position,
769 const gchar *label_text, const gchar *tooltip_text,
770 const enum_val_t *enumvals, gint current_val)
772 GtkTooltips *tooltips;
773 GtkWidget *menu_box, *menu, *menu_item, *option_menu;
774 int menu_index, index;
775 const enum_val_t *enum_valp;
776 GtkWidget *event_box;
778 tooltips = g_object_get_data(G_OBJECT(main_tb), E_TOOLTIPS_KEY);
780 set_option_label(main_tb, table_position, label_text, tooltip_text,
783 /* Create a menu from the enumvals */
784 menu = gtk_menu_new();
785 if (tooltip_text != NULL && tooltips != NULL)
786 gtk_tooltips_set_tip(tooltips, menu, tooltip_text, NULL);
788 for (enum_valp = enumvals, index = 0; enum_valp->name != NULL;
789 enum_valp++, index++) {
790 menu_item = gtk_menu_item_new_with_label(enum_valp->description);
791 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
792 if (enum_valp->value == current_val)
794 gtk_widget_show(menu_item);
797 /* Create the option menu from the menu */
798 option_menu = gtk_option_menu_new();
799 gtk_option_menu_set_menu(GTK_OPTION_MENU(option_menu), menu);
801 /* Set its current value to the variable's current value */
802 if (menu_index != -1)
803 gtk_option_menu_set_history(GTK_OPTION_MENU(option_menu),
807 * Put the option menu in an hbox, so that it's only as wide
808 * as the widest entry, rather than being as wide as the table
811 menu_box = gtk_hbox_new(FALSE, 0);
812 gtk_box_pack_start(GTK_BOX(menu_box), option_menu, FALSE, FALSE, 0);
814 event_box = gtk_event_box_new();
815 gtk_event_box_set_visible_window (GTK_EVENT_BOX(event_box), FALSE);
816 gtk_table_attach_defaults(GTK_TABLE(main_tb), event_box,
817 1, 2, table_position, table_position + 1);
818 if (tooltip_text != NULL && tooltips != NULL)
819 gtk_tooltips_set_tip(tooltips, event_box, tooltip_text, NULL);
820 gtk_container_add(GTK_CONTAINER(event_box), menu_box);
826 fetch_preference_option_menu_val(GtkWidget *optmenu, const enum_val_t *enumvals)
829 * OK, now return the value corresponding to the label for the
830 * currently active entry in the option menu.
832 * Yes, this is how you get the label for that entry. See FAQ
833 * 6.8 in the GTK+ FAQ.
835 return label_to_enum_val(GTK_BIN(optmenu)->child, enumvals);
839 create_preference_entry(GtkWidget *main_tb, int table_position,
840 const gchar *label_text, const gchar *tooltip_text, char *value)
842 GtkTooltips *tooltips;
845 tooltips = g_object_get_data(G_OBJECT(main_tb), E_TOOLTIPS_KEY);
847 set_option_label(main_tb, table_position, label_text, tooltip_text,
850 entry = gtk_entry_new();
852 gtk_entry_set_text(GTK_ENTRY(entry), value);
853 gtk_table_attach_defaults(GTK_TABLE(main_tb), entry, 1, 2,
854 table_position, table_position + 1);
855 if (tooltip_text != NULL && tooltips != NULL)
856 gtk_tooltips_set_tip(tooltips, entry, tooltip_text, NULL);
857 gtk_widget_show(entry);
863 create_preference_static_text(GtkWidget *main_tb, int table_position,
864 const gchar *label_text, const gchar *tooltip_text)
866 GtkTooltips *tooltips;
869 tooltips = g_object_get_data(G_OBJECT(main_tb), E_TOOLTIPS_KEY);
871 if(label_text != NULL)
872 label = gtk_label_new(label_text);
874 label = gtk_label_new("");
875 gtk_table_attach_defaults(GTK_TABLE(main_tb), label, 0, 2,
876 table_position, table_position + 1);
877 if (tooltip_text != NULL && tooltips != NULL)
878 gtk_tooltips_set_tip(tooltips, label, tooltip_text, NULL);
879 gtk_widget_show(label);
885 create_preference_uat(GtkWidget *main_tb, int table_position,
886 const gchar *label_text, const gchar *tooltip_text, void* uat)
888 GtkTooltips *tooltips;
889 GtkWidget *button = NULL;
891 tooltips = g_object_get_data(G_OBJECT(main_tb), E_TOOLTIPS_KEY);
893 set_option_label(main_tb, table_position, label_text, tooltip_text,
896 button = gtk_button_new_from_stock(WIRESHARK_STOCK_EDIT);
898 g_signal_connect(button, "clicked", G_CALLBACK(uat_window_cb), uat);
900 gtk_table_attach_defaults(GTK_TABLE(main_tb), button, 1, 2,
901 table_position, table_position+1);
902 if (tooltip_text != NULL && tooltips != NULL)
903 gtk_tooltips_set_tip(tooltips, button, tooltip_text, NULL);
904 gtk_widget_show(button);
911 pref_check(pref_t *pref, gpointer user_data)
916 pref_t **badpref = user_data;
918 /* Fetch the value of the preference, and check whether it's valid. */
919 switch (pref->type) {
922 str_val = gtk_entry_get_text(GTK_ENTRY(pref->control));
923 uval = strtoul(str_val, &p, pref->info.base);
924 if (p == str_val || *p != '\0') {
926 return PREFS_SET_SYNTAX_ERR; /* number was bad */
931 /* Value can't be bad. */
935 /* Value can't be bad. */
939 /* Value can't be bad. */
943 str_val = gtk_entry_get_text(GTK_ENTRY(pref->control));
945 if (strlen(str_val) != 0) {
948 if (range_convert_str(&newrange, str_val, pref->info.max_value) !=
951 return PREFS_SET_SYNTAX_ERR; /* range was bad */
957 case PREF_STATIC_TEXT:
959 /* Value can't be bad. */
963 g_assert_not_reached();
970 module_prefs_check(module_t *module, gpointer user_data)
972 /* For all preferences in this module, fetch its value from this
973 module's notebook page and check whether it's valid. */
974 return prefs_pref_foreach(module, pref_check, user_data);
978 pref_fetch(pref_t *pref, gpointer user_data)
985 gboolean *pref_changed_p = user_data;
987 /* Fetch the value of the preference, and set the appropriate variable
989 switch (pref->type) {
992 str_val = gtk_entry_get_text(GTK_ENTRY(pref->control));
993 uval = strtoul(str_val, &p, pref->info.base);
995 if (p == value || *p != '\0')
996 return PREFS_SET_SYNTAX_ERR; /* number was bad */
998 if (*pref->varp.uint != uval) {
999 *pref_changed_p = TRUE;
1000 *pref->varp.uint = uval;
1005 bval = GTK_TOGGLE_BUTTON(pref->control)->active;
1006 if (*pref->varp.boolp != bval) {
1007 *pref_changed_p = TRUE;
1008 *pref->varp.boolp = bval;
1013 if (pref->info.enum_info.radio_buttons) {
1014 enumval = fetch_preference_radio_buttons_val(pref->control,
1015 pref->info.enum_info.enumvals);
1017 enumval = fetch_preference_option_menu_val(pref->control,
1018 pref->info.enum_info.enumvals);
1021 if (*pref->varp.enump != enumval) {
1022 *pref_changed_p = TRUE;
1023 *pref->varp.enump = enumval;
1028 str_val = gtk_entry_get_text(GTK_ENTRY(pref->control));
1029 if (strcmp(*pref->varp.string, str_val) != 0) {
1030 *pref_changed_p = TRUE;
1031 g_free((void *)*pref->varp.string);
1032 *pref->varp.string = g_strdup(str_val);
1041 str_val = gtk_entry_get_text(GTK_ENTRY(pref->control));
1042 ret = range_convert_str(&newrange, str_val, pref->info.max_value);
1043 if (ret != CVT_NO_ERROR)
1045 return PREFS_SET_SYNTAX_ERR; /* range was bad */
1047 return 0; /* XXX - should fail */
1050 if (!ranges_are_equal(*pref->varp.range, newrange)) {
1051 *pref_changed_p = TRUE;
1052 g_free(*pref->varp.range);
1053 *pref->varp.range = newrange;
1060 case PREF_STATIC_TEXT:
1065 g_assert_not_reached();
1072 module_prefs_fetch(module_t *module, gpointer user_data)
1074 gboolean *must_redissect_p = user_data;
1076 /* For all preferences in this module, fetch its value from this
1077 module's notebook page. Find out whether any of them changed. */
1078 module->prefs_changed = FALSE; /* assume none of them changed */
1079 prefs_pref_foreach(module, pref_fetch, &module->prefs_changed);
1081 /* If any of them changed, indicate that we must redissect and refilter
1082 the current capture (if we have one), as the preference change
1083 could cause packets to be dissected differently. */
1084 if (module->prefs_changed)
1085 *must_redissect_p = TRUE;
1087 return 0; /* keep fetching module preferences */
1092 * This function is used to apply changes and update the Wireless Toolbar
1093 * whenever we apply some changes to the WEP preferences
1096 prefs_airpcap_update()
1098 GtkWidget *decryption_cm;
1099 GtkWidget *decryption_en;
1100 gboolean wireshark_decryption_was_enabled;
1101 gboolean airpcap_decryption_was_enabled;
1102 gboolean wireshark_decryption_is_now_enabled;
1104 decryption_cm = GTK_WIDGET(g_object_get_data(G_OBJECT(airpcap_tb),AIRPCAP_TOOLBAR_DECRYPTION_KEY));
1105 decryption_en = GTK_WIDGET(GTK_ENTRY(GTK_COMBO(decryption_cm)->entry));
1107 if( g_ascii_strcasecmp(gtk_entry_get_text(GTK_ENTRY(decryption_en)),AIRPCAP_DECRYPTION_TYPE_STRING_WIRESHARK) == 0 )
1109 wireshark_decryption_was_enabled = TRUE;
1110 airpcap_decryption_was_enabled = FALSE;
1112 else if( g_ascii_strcasecmp(gtk_entry_get_text(GTK_ENTRY(decryption_en)),AIRPCAP_DECRYPTION_TYPE_STRING_AIRPCAP) == 0 )
1114 wireshark_decryption_was_enabled = FALSE;
1115 airpcap_decryption_was_enabled = TRUE;
1117 else if( g_ascii_strcasecmp(gtk_entry_get_text(GTK_ENTRY(decryption_en)),AIRPCAP_DECRYPTION_TYPE_STRING_NONE) == 0 )
1119 wireshark_decryption_was_enabled = FALSE;
1120 airpcap_decryption_was_enabled = FALSE;
1123 wireshark_decryption_is_now_enabled = wireshark_decryption_on();
1125 if(wireshark_decryption_is_now_enabled && airpcap_decryption_was_enabled)
1127 set_airpcap_decryption(FALSE);
1128 gtk_entry_set_text(GTK_ENTRY(decryption_en),AIRPCAP_DECRYPTION_TYPE_STRING_WIRESHARK);
1130 if(wireshark_decryption_is_now_enabled && !airpcap_decryption_was_enabled)
1132 set_airpcap_decryption(FALSE);
1133 gtk_entry_set_text(GTK_ENTRY(decryption_en),AIRPCAP_DECRYPTION_TYPE_STRING_WIRESHARK);
1135 else if(!wireshark_decryption_is_now_enabled && wireshark_decryption_was_enabled)
1137 if(airpcap_decryption_was_enabled)
1139 set_airpcap_decryption(TRUE);
1140 gtk_entry_set_text(GTK_ENTRY(decryption_en),AIRPCAP_DECRYPTION_TYPE_STRING_AIRPCAP);
1144 set_airpcap_decryption(FALSE);
1145 gtk_entry_set_text(GTK_ENTRY(decryption_en),AIRPCAP_DECRYPTION_TYPE_STRING_NONE);
1152 pref_clean(pref_t *pref, gpointer user_data _U_)
1154 switch (pref->type) {
1166 if (pref->saved_val.string != NULL) {
1167 g_free(pref->saved_val.string);
1168 pref->saved_val.string = NULL;
1173 if (pref->saved_val.range != NULL) {
1174 g_free(pref->saved_val.range);
1175 pref->saved_val.range = NULL;
1179 case PREF_STATIC_TEXT:
1184 g_assert_not_reached();
1191 module_prefs_clean(module_t *module, gpointer user_data _U_)
1193 /* For all preferences in this module, clean up any cruft allocated for
1194 use by the GUI code. */
1195 prefs_pref_foreach(module, pref_clean, NULL);
1196 return 0; /* keep cleaning modules */
1199 /* fetch all pref values from all pages */
1201 prefs_main_fetch_all(GtkWidget *dlg, gboolean *must_redissect)
1205 /* First, check that the values are all valid. */
1206 /* XXX - check the non-registered preferences too */
1207 switch (prefs_modules_foreach(module_prefs_check, (gpointer)&badpref)) {
1209 case PREFS_SET_SYNTAX_ERR:
1210 switch (badpref->type) {
1213 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1214 "The value for \"%s\" isn't a valid number.",
1219 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1220 "The value for \"%s\" isn't a valid range.",
1225 g_assert_not_reached();
1230 /* Fetch the preferences (i.e., make sure all the values set in all of
1231 the preferences panes have been copied to "prefs" and the registered
1233 gui_prefs_fetch(g_object_get_data(G_OBJECT(dlg), E_GUI_PAGE_KEY));
1234 layout_prefs_fetch(g_object_get_data(G_OBJECT(dlg), E_GUI_LAYOUT_PAGE_KEY));
1235 column_prefs_fetch(g_object_get_data(G_OBJECT(dlg), E_GUI_COLUMN_PAGE_KEY));
1236 stream_prefs_fetch(g_object_get_data(G_OBJECT(dlg), E_GUI_COLORS_PAGE_KEY));
1240 /* Is WPcap loaded? */
1243 capture_prefs_fetch(g_object_get_data(G_OBJECT(dlg), E_CAPTURE_PAGE_KEY));
1247 #endif /* HAVE_LIBPCAP */
1248 printer_prefs_fetch(g_object_get_data(G_OBJECT(dlg), E_PRINT_PAGE_KEY));
1249 nameres_prefs_fetch(g_object_get_data(G_OBJECT(dlg), E_NAMERES_PAGE_KEY));
1250 stats_prefs_fetch(g_object_get_data(G_OBJECT(dlg), E_TAPS_PAGE_KEY));
1251 protocols_prefs_fetch(g_object_get_data(G_OBJECT(dlg), E_PROTOCOLS_PAGE_KEY));
1252 prefs_modules_foreach(module_prefs_fetch, must_redissect);
1257 /* apply all pref values to the real world */
1259 prefs_main_apply_all(GtkWidget *dlg, gboolean redissect)
1264 * Apply the protocol preferences first - "gui_prefs_apply()" could
1265 * cause redissection, and we have to make sure the protocol
1266 * preference changes have been fully applied.
1270 gui_prefs_apply(g_object_get_data(G_OBJECT(dlg), E_GUI_PAGE_KEY), redissect);
1271 layout_prefs_apply(g_object_get_data(G_OBJECT(dlg), E_GUI_LAYOUT_PAGE_KEY));
1272 column_prefs_apply(g_object_get_data(G_OBJECT(dlg), E_GUI_COLUMN_PAGE_KEY));
1273 stream_prefs_apply(g_object_get_data(G_OBJECT(dlg), E_GUI_COLORS_PAGE_KEY));
1277 /* Is WPcap loaded? */
1280 capture_prefs_apply(g_object_get_data(G_OBJECT(dlg), E_CAPTURE_PAGE_KEY));
1284 #endif /* HAVE_LIBPCAP */
1285 printer_prefs_apply(g_object_get_data(G_OBJECT(dlg), E_PRINT_PAGE_KEY));
1286 nameres_prefs_apply(g_object_get_data(G_OBJECT(dlg), E_NAMERES_PAGE_KEY));
1287 stats_prefs_apply(g_object_get_data(G_OBJECT(dlg), E_TAPS_PAGE_KEY));
1288 protocols_prefs_apply(g_object_get_data(G_OBJECT(dlg), E_PROTOCOLS_PAGE_KEY));
1290 /* show/hide the Save button - depending on setting */
1291 save_bt = g_object_get_data(G_OBJECT(prefs_w), E_PREFSW_SAVE_BT_KEY);
1292 if(prefs.gui_use_pref_save) {
1293 gtk_widget_show(save_bt);
1295 gtk_widget_hide(save_bt);
1300 /* destroy all preferences ressources from all pages */
1302 prefs_main_destroy_all(GtkWidget *dlg)
1308 (frame = gtk_notebook_get_nth_page(g_object_get_data(G_OBJECT(prefs_w), E_PREFSW_NOTEBOOK_KEY), page_num)) != NULL;
1310 if(g_object_get_data(G_OBJECT(frame), E_PAGE_ITER_KEY))
1311 gtk_tree_iter_free(g_object_get_data(G_OBJECT(frame), E_PAGE_ITER_KEY));
1314 gui_prefs_destroy(g_object_get_data(G_OBJECT(dlg), E_GUI_PAGE_KEY));
1315 layout_prefs_destroy(g_object_get_data(G_OBJECT(dlg), E_GUI_LAYOUT_PAGE_KEY));
1316 column_prefs_destroy(g_object_get_data(G_OBJECT(dlg), E_GUI_COLUMN_PAGE_KEY));
1317 stream_prefs_destroy(g_object_get_data(G_OBJECT(dlg), E_GUI_COLORS_PAGE_KEY));
1321 /* Is WPcap loaded? */
1324 capture_prefs_destroy(g_object_get_data(G_OBJECT(dlg), E_CAPTURE_PAGE_KEY));
1328 #endif /* HAVE_LIBPCAP */
1329 printer_prefs_destroy(g_object_get_data(G_OBJECT(dlg), E_PRINT_PAGE_KEY));
1330 nameres_prefs_destroy(g_object_get_data(G_OBJECT(dlg), E_NAMERES_PAGE_KEY));
1331 stats_prefs_destroy(g_object_get_data(G_OBJECT(dlg), E_TAPS_PAGE_KEY));
1333 /* Free up the saved preferences (both for "prefs" and for registered
1335 free_prefs(&saved_prefs);
1336 prefs_modules_foreach(module_prefs_clean, NULL);
1337 protocols_prefs_destroy(g_object_get_data(G_OBJECT(dlg), E_PROTOCOLS_PAGE_KEY));
1342 prefs_main_write(void)
1348 /* Create the directory that holds personal configuration files, if
1350 if (create_persconffile_dir(&pf_dir_path) == -1) {
1351 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1352 "Can't create directory\n\"%s\"\nfor preferences file: %s.", pf_dir_path,
1354 g_free(pf_dir_path);
1356 /* Write the preferencs out. */
1357 err = write_prefs(&pf_path);
1359 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1360 "Can't open preferences file\n\"%s\": %s.", pf_path,
1368 * Load the Wireshark decryption keys (just set) and save
1369 * the changes to the adapters' registry
1371 airpcap_load_decryption_keys(airpcap_if_list);
1377 prefs_main_ok_cb(GtkWidget *ok_bt _U_, gpointer parent_w)
1379 gboolean must_redissect = FALSE;
1381 if (!prefs_main_fetch_all(parent_w, &must_redissect))
1382 return; /* Errors in some preference setting - already reported */
1384 /* if we don't have a Save button, just save the settings now */
1385 if (!prefs.gui_use_pref_save) {
1389 prefs_main_apply_all(parent_w, must_redissect);
1391 /* Fill in capture options with values from the preferences */
1392 prefs_to_capture_opts();
1395 prefs_airpcap_update();
1398 /* Now destroy the "Preferences" dialog. */
1399 window_destroy(GTK_WIDGET(parent_w));
1401 if (must_redissect) {
1402 /* Redissect all the packets, and re-evaluate the display filter. */
1403 cf_redissect_packets(&cfile);
1409 prefs_main_apply_cb(GtkWidget *apply_bt _U_, gpointer parent_w)
1411 gboolean must_redissect = FALSE;
1413 if (!prefs_main_fetch_all(parent_w, &must_redissect))
1414 return; /* Errors in some preference setting - already reported */
1416 /* if we don't have a Save button, just save the settings now */
1417 if (!prefs.gui_use_pref_save) {
1421 prefs_main_apply_all(parent_w, must_redissect);
1423 /* Fill in capture options with values from the preferences */
1424 prefs_to_capture_opts();
1427 prefs_airpcap_update();
1430 if (must_redissect) {
1431 /* Redissect all the packets, and re-evaluate the display filter. */
1432 cf_redissect_packets(&cfile);
1437 prefs_main_save_cb(GtkWidget *save_bt _U_, gpointer parent_w)
1439 gboolean must_redissect = FALSE;
1441 if (!prefs_main_fetch_all(parent_w, &must_redissect))
1442 return; /* Errors in some preference setting - already reported */
1446 /* Now apply those preferences.
1447 XXX - should we do this? The user didn't click "OK" or "Apply".
1450 1) by saving the preferences they presumably indicate that they
1453 2) the next time they fire Wireshark up, those preferences will
1456 3) we'd have to buffer "must_redissect" so that if they do
1457 "Apply" after this, we know we have to redissect;
1459 4) we did apply the protocol preferences, at least, in the past. */
1460 prefs_main_apply_all(parent_w, must_redissect);
1462 /* Fill in capture options with values from the preferences */
1463 prefs_to_capture_opts();
1465 if (must_redissect) {
1466 /* Redissect all the packets, and re-evaluate the display filter. */
1467 cf_redissect_packets(&cfile);
1472 pref_revert(pref_t *pref, gpointer user_data)
1474 gboolean *pref_changed_p = user_data;
1476 /* Revert the preference to its saved value. */
1477 switch (pref->type) {
1480 if (*pref->varp.uint != pref->saved_val.uint) {
1481 *pref_changed_p = TRUE;
1482 *pref->varp.uint = pref->saved_val.uint;
1487 if (*pref->varp.boolp != pref->saved_val.boolval) {
1488 *pref_changed_p = TRUE;
1489 *pref->varp.boolp = pref->saved_val.boolval;
1494 if (*pref->varp.enump != pref->saved_val.enumval) {
1495 *pref_changed_p = TRUE;
1496 *pref->varp.enump = pref->saved_val.enumval;
1501 if (strcmp(*pref->varp.string, pref->saved_val.string) != 0) {
1502 *pref_changed_p = TRUE;
1503 g_free((void *)*pref->varp.string);
1504 *pref->varp.string = g_strdup(pref->saved_val.string);
1509 if (!ranges_are_equal(*pref->varp.range, pref->saved_val.range)) {
1510 *pref_changed_p = TRUE;
1511 g_free(*pref->varp.range);
1512 *pref->varp.range = range_copy(pref->saved_val.range);
1516 case PREF_STATIC_TEXT:
1521 g_assert_not_reached();
1528 module_prefs_revert(module_t *module, gpointer user_data)
1530 gboolean *must_redissect_p = user_data;
1532 /* For all preferences in this module, revert its value to the value
1533 it had when we popped up the Preferences dialog. Find out whether
1534 this changes any of them. */
1535 module->prefs_changed = FALSE; /* assume none of them changed */
1536 prefs_pref_foreach(module, pref_revert, &module->prefs_changed);
1538 /* If any of them changed, indicate that we must redissect and refilter
1539 the current capture (if we have one), as the preference change
1540 could cause packets to be dissected differently. */
1541 if (module->prefs_changed)
1542 *must_redissect_p = TRUE;
1543 return 0; /* keep processing modules */
1546 /* cancel button pressed, revert prefs to saved and exit dialog */
1548 prefs_main_cancel_cb(GtkWidget *cancel_bt _U_, gpointer parent_w)
1550 gboolean must_redissect = FALSE;
1552 /* Free up the current preferences and copy the saved preferences to the
1553 current preferences. */
1555 copy_prefs(&prefs, &saved_prefs);
1557 /* Now revert the registered preferences. */
1558 prefs_modules_foreach(module_prefs_revert, &must_redissect);
1560 /* Now apply the reverted-to preferences. */
1561 prefs_main_apply_all(parent_w, must_redissect);
1563 window_destroy(GTK_WIDGET(parent_w));
1565 if (must_redissect) {
1566 /* Redissect all the packets, and re-evaluate the display filter. */
1567 cf_redissect_packets(&cfile);
1571 /* Treat this as a cancel, by calling "prefs_main_cancel_cb()" */
1573 prefs_main_delete_event_cb(GtkWidget *prefs_w, GdkEvent *event _U_,
1574 gpointer parent_w _U_)
1576 prefs_main_cancel_cb(NULL, prefs_w);
1581 /* dialog *is* already destroyed, clean up memory and such */
1583 prefs_main_destroy_cb(GtkWidget *win _U_, gpointer parent_w)
1585 prefs_main_destroy_all(parent_w);
1587 /* Note that we no longer have a "Preferences" dialog box. */
1591 struct properties_data {
1597 module_search_properties(module_t *module, gpointer user_data)
1599 struct properties_data *p = (struct properties_data *)user_data;
1601 /* If this module has the specified title, remember it. */
1602 if (strcmp(module->title, p->title) == 0) {
1604 return 1; /* stops the search */
1607 if(prefs_module_has_submodules(module))
1608 return prefs_modules_foreach_submodules(module, module_search_properties, p);
1614 tree_expand_row(GtkTreeModel *model, GtkTreeView *tree_view, GtkTreeIter *iter)
1619 /* expand the parent first */
1620 if(gtk_tree_model_iter_parent(model, &parent, iter))
1621 tree_expand_row(model, tree_view, &parent);
1623 path = gtk_tree_model_get_path(model, iter);
1624 gtk_tree_view_expand_row(tree_view, path, FALSE);
1625 /*expand_tree(tree_view, &parent, NULL, NULL);*/
1627 gtk_tree_path_free(path);
1630 /* select a node in the tree view */
1631 /* XXX - this is almost 100% copied from byte_view_select() in proto_draw.c,
1632 * find a way to combine both to have a generic function for this */
1634 tree_select_node(GtkWidget *tree, prefs_tree_iter *iter)
1636 GtkTreeIter local_iter = *iter;
1637 GtkTreeView *tree_view = GTK_TREE_VIEW(tree);
1638 GtkTreeModel *model;
1639 GtkTreePath *first_path;
1641 model = gtk_tree_view_get_model(tree_view);
1643 /* Expand our field's row */
1644 first_path = gtk_tree_model_get_path(model, &local_iter);
1646 /* expand from the top down */
1647 tree_expand_row(model, tree_view, &local_iter);
1649 /* select our field's row */
1650 gtk_tree_selection_select_path(gtk_tree_view_get_selection(tree_view),
1653 /* And position the window so the selection is visible.
1654 * Position the selection in the middle of the viewable
1656 gtk_tree_view_scroll_to_cell(tree_view, first_path, NULL, TRUE, 0.5, 0.0);
1658 gtk_tree_path_free(first_path);
1662 /* search the corresponding protocol page of the currently selected field */
1664 properties_cb(GtkWidget *w, gpointer dummy)
1666 header_field_info *hfinfo;
1668 struct properties_data p;
1672 module_t *page_module;
1674 if (cfile.finfo_selected == NULL) {
1675 /* There is no field selected */
1679 /* Find the title for the protocol for the selected field. */
1680 hfinfo = cfile.finfo_selected->hfinfo;
1681 if (hfinfo->parent == -1)
1682 title = prefs_get_title_by_name(hfinfo->abbrev);
1684 title = prefs_get_title_by_name(proto_registrar_get_abbrev(hfinfo->parent));
1686 return; /* Couldn't find it. XXX - just crash? "Can't happen"? */
1688 /* Find the module for that protocol by searching for one with that title.
1689 XXX - should we just associate protocols with modules directly? */
1692 prefs_modules_foreach_submodules(protocols_module, module_search_properties,
1694 if (p.module == NULL) {
1695 /* We didn't find it - that protocol probably has no preferences. */
1699 /* Create a preferences window, or pop up an existing one. */
1700 if (prefs_w != NULL) {
1701 reactivate_window(prefs_w);
1706 /* Search all the pages in that window for the one with the specified
1709 (sw = gtk_notebook_get_nth_page(g_object_get_data(G_OBJECT(prefs_w), E_PREFSW_NOTEBOOK_KEY), page_num)) != NULL;
1711 /* Get the frame from the scrollable window */
1712 frame = g_object_get_data(G_OBJECT(sw), E_PAGESW_FRAME_KEY);
1713 /* Get the module for this page (non-protocol prefs don't have one). */
1715 page_module = g_object_get_data(G_OBJECT(frame), E_PAGE_MODULE_KEY);
1716 if (page_module != NULL) {
1717 if (page_module == p.module) {
1719 g_object_get_data(G_OBJECT(prefs_w), E_PREFSW_TREE_KEY),
1720 g_object_get_data(G_OBJECT(frame), E_PAGE_ITER_KEY));
1728 /* Prefs tree selection callback. The node data has been loaded with
1729 the proper notebook page to load. */
1731 prefs_tree_select_cb(GtkTreeSelection *sel, gpointer dummy _U_)
1734 GtkTreeModel *model;
1737 if (gtk_tree_selection_get_selected(sel, &model, &iter))
1739 gtk_tree_model_get(model, &iter, 1, &page, -1);
1741 gtk_notebook_set_current_page(g_object_get_data(G_OBJECT(prefs_w), E_PREFSW_NOTEBOOK_KEY), page);