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;
123 gboolean is_protocol;
126 static gint protocols_page = 0;
129 pref_exists(pref_t *pref _U_, gpointer user_data _U_)
134 /* show a single preference on the GtkTable of a preference page */
136 pref_show(pref_t *pref, gpointer user_data)
138 GtkWidget *main_tb = user_data;
144 /* Give this preference a label which is its title, followed by a colon,
145 and left-align it. */
147 label_len = strlen(title) + 2;
148 label_string = g_malloc(label_len);
149 g_strlcpy(label_string, title, label_len);
152 * Sometimes we don't want to append a ':' after a static text string...
153 * If it is needed, we will specify it in the string itself.
155 if(pref->type != PREF_STATIC_TEXT)
156 g_strlcat(label_string, ":", label_len);
158 /* Save the current value of the preference, so that we can revert it if
159 the user does "Apply" and then "Cancel", and create the control for
160 editing the preference. */
161 switch (pref->type) {
164 pref->saved_val.uint = *pref->varp.uint;
166 /* XXX - there are no uint spinbuttons, so we can't use a spinbutton.
167 Even more annoyingly, even if there were, GLib doesn't define
168 G_MAXUINT - but I think ANSI C may define UINT_MAX, so we could
170 switch (pref->info.base) {
173 g_snprintf(uint_str, sizeof(uint_str), "%u", pref->saved_val.uint);
177 g_snprintf(uint_str, sizeof(uint_str), "%o", pref->saved_val.uint);
181 g_snprintf(uint_str, sizeof(uint_str), "%x", pref->saved_val.uint);
184 pref->control = create_preference_entry(main_tb, pref->ordinal,
185 label_string, pref->description,
190 pref->saved_val.boolval = *pref->varp.boolp;
191 pref->control = create_preference_check_button(main_tb, pref->ordinal,
192 label_string, pref->description,
193 pref->saved_val.boolval);
197 pref->saved_val.enumval = *pref->varp.enump;
198 if (pref->info.enum_info.radio_buttons) {
199 /* Show it as radio buttons. */
200 pref->control = create_preference_radio_buttons(main_tb, pref->ordinal,
201 label_string, pref->description,
202 pref->info.enum_info.enumvals,
203 pref->saved_val.enumval);
205 /* Show it as an option menu. */
206 pref->control = create_preference_option_menu(main_tb, pref->ordinal,
207 label_string, pref->description,
208 pref->info.enum_info.enumvals,
209 pref->saved_val.enumval);
214 g_free(pref->saved_val.string);
215 pref->saved_val.string = g_strdup(*pref->varp.string);
216 pref->control = create_preference_entry(main_tb, pref->ordinal,
217 label_string, pref->description,
218 pref->saved_val.string);
225 g_free(pref->saved_val.range);
226 pref->saved_val.range = range_copy(*pref->varp.range);
227 range_str_p = range_convert_range(*pref->varp.range);
228 pref->control = create_preference_entry(main_tb, pref->ordinal,
229 label_string, pref->description,
234 case PREF_STATIC_TEXT:
236 pref->control = create_preference_static_text(main_tb, pref->ordinal,
237 label_string, pref->description);
243 pref->control = create_preference_uat(main_tb, pref->ordinal,
244 label_string, pref->description,
250 g_assert_not_reached();
253 g_free(label_string);
258 #define MAX_TREE_NODE_NAME_LEN 64
259 /* show prefs page for each registered module (protocol) */
261 module_prefs_show(module_t *module, gpointer user_data)
263 struct ct_struct *cts = user_data;
264 struct ct_struct child_cts;
265 GtkWidget *main_vb, *main_tb, *frame, *main_sw;
266 gchar label_str[MAX_TREE_NODE_NAME_LEN];
271 * Is this module a subtree, with modules underneath it?
273 if (!prefs_module_has_submodules(module)) {
276 * Does it have any preferences (other than possibly obsolete ones)?
278 if (prefs_pref_foreach(module, pref_exists, NULL) == 0) {
280 * No. Don't put the module into the preferences window.
281 * XXX - we should do the same for subtrees; if a subtree has
282 * nothing under it that will be displayed, don't put it into
290 * Add this module to the tree.
292 g_strlcpy(label_str, module->title, MAX_TREE_NODE_NAME_LEN);
293 model = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(cts->tree)));
294 if (prefs_module_has_submodules(module) && !cts->iter.stamp)
295 gtk_tree_store_append(model, &iter, NULL);
297 gtk_tree_store_append(model, &iter, &cts->iter);
302 if (prefs_module_has_submodules(module)) {
307 gtk_tree_store_set(model, &iter, 0, label_str, 1, -1, -1);
310 * Walk the subtree and attach stuff to it.
313 child_cts.iter = iter;
314 if (module == protocols_module)
315 child_cts.is_protocol = TRUE;
316 prefs_modules_foreach_submodules(module, module_prefs_show, &child_cts);
318 /* keep the page count right */
319 cts->page = child_cts.page;
324 * Has preferences. Create a notebook page for it.
327 /* Scrolled window */
328 main_sw = gtk_scrolled_window_new(NULL, NULL);
329 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(main_sw), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
332 frame = gtk_frame_new(module->description);
333 gtk_container_set_border_width(GTK_CONTAINER(frame), 5);
334 gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(main_sw), frame);
335 g_object_set_data(G_OBJECT(main_sw), E_PAGESW_FRAME_KEY, frame);
337 /* Main vertical box */
338 main_vb = gtk_vbox_new(FALSE, 5);
339 gtk_container_set_border_width(GTK_CONTAINER(main_vb), 5);
340 gtk_container_add(GTK_CONTAINER(frame), main_vb);
343 main_tb = gtk_table_new(module->numprefs, 2, FALSE);
344 gtk_box_pack_start(GTK_BOX(main_vb), main_tb, FALSE, FALSE, 0);
345 gtk_table_set_row_spacings(GTK_TABLE(main_tb), 10);
346 gtk_table_set_col_spacings(GTK_TABLE(main_tb), 15);
348 /* Add items for each of the preferences */
349 prefs_pref_foreach(module, pref_show, main_tb);
351 /* Associate this module with the page's frame. */
352 g_object_set_data(G_OBJECT(frame), E_PAGE_MODULE_KEY, module);
354 /* Add the page to the notebook */
355 gtk_notebook_append_page(GTK_NOTEBOOK(cts->notebook), main_sw, NULL);
357 /* Attach the page to the tree item */
358 gtk_tree_store_set(model, &iter, 0, label_str, 1, cts->page, -1);
359 g_object_set_data(G_OBJECT(frame), E_PAGE_ITER_KEY, gtk_tree_iter_copy(&iter));
363 /* Show 'em what we got */
364 gtk_widget_show_all(main_sw);
366 /* show the protocols page */
368 gtk_tree_store_set(model, &iter, 0, label_str, 1, protocols_page, -1);
376 #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 prefs_tree_iter iter;
385 gtk_tree_store_append(store, &iter, parent_iter);
386 gtk_tree_store_set(store, &iter, 0, title, 1, page_nr, -1);
390 /* add a page to the notebook */
392 prefs_nb_page_add(GtkWidget *notebook, const gchar *title, GtkWidget *page, const char *page_key)
396 frame = gtk_frame_new(title);
397 gtk_widget_show(frame);
399 gtk_container_add(GTK_CONTAINER(frame), page);
400 g_object_set_data(G_OBJECT(prefs_w), page_key, page);
402 gtk_notebook_append_page (GTK_NOTEBOOK(notebook), frame, NULL);
408 /* show the dialog */
410 prefs_cb(GtkWidget *w, gpointer dummy)
412 prefs_page_cb (w, dummy, PREFS_PAGE_USER_INTERFACE);
416 prefs_page_cb(GtkWidget *w _U_, gpointer dummy _U_, PREFS_PAGE_E prefs_page)
418 GtkWidget *top_hb, *bbox, *prefs_nb, *ct_sb,
419 *ok_bt, *apply_bt, *save_bt, *cancel_bt, *help_bt;
420 GtkWidget *gui_font_pg;
421 gchar label_str[MAX_TREE_NODE_NAME_LEN];
422 struct ct_struct cts;
424 GtkTreeSelection *selection;
425 GtkCellRenderer *renderer;
426 GtkTreeViewColumn *column;
428 prefs_tree_iter gui_iter, layout_iter, columns_iter;
429 gint layout_page, columns_page;
432 if (prefs_w != NULL) {
433 /* There's already a "Preferences" dialog box; reactivate it. */
434 reactivate_window(prefs_w);
438 /* Save the current preferences, so we can revert to those values
439 if the user presses "Cancel". */
440 copy_prefs(&saved_prefs, &prefs);
442 prefs_w = dlg_conf_window_new("Wireshark: Preferences");
445 * Unfortunately, we can't arrange that a GtkTable widget wrap an event box
446 * around a table row, so the spacing between the preference item's label
447 * and its control widgets is inactive and the tooltip doesn't pop up when
448 * the mouse is over it.
451 /* Container for each row of widgets */
452 cts.main_vb = gtk_vbox_new(FALSE, 5);
453 gtk_container_set_border_width(GTK_CONTAINER(cts.main_vb), 5);
454 gtk_container_add(GTK_CONTAINER(prefs_w), cts.main_vb);
455 gtk_widget_show(cts.main_vb);
457 /* Top row: Preferences tree and notebook */
458 top_hb = gtk_hbox_new(FALSE, 10);
459 gtk_container_add(GTK_CONTAINER(cts.main_vb), top_hb);
460 gtk_widget_show(top_hb);
462 /* scrolled window on the left for the categories tree */
463 ct_sb = scrolled_window_new(NULL, NULL);
464 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(ct_sb),
466 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(ct_sb),
467 GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
468 gtk_container_add(GTK_CONTAINER(top_hb), ct_sb);
469 gtk_widget_show(ct_sb);
470 g_object_set_data(G_OBJECT(prefs_w), E_PREFSW_SCROLLW_KEY, ct_sb);
472 /* categories tree */
473 store = gtk_tree_store_new(2, G_TYPE_STRING, G_TYPE_INT);
474 cts.tree = tree_view_new(GTK_TREE_MODEL(store));
475 cts.iter.stamp = 0; /* mark this as the toplevel */
476 g_object_set_data(G_OBJECT(prefs_w), E_PREFSW_TREE_KEY, cts.tree);
477 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(cts.tree), FALSE);
478 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(cts.tree));
479 gtk_tree_selection_set_mode(selection, GTK_SELECTION_SINGLE);
480 renderer = gtk_cell_renderer_text_new();
481 col_offset = gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(cts.tree),
482 -1, "Name", renderer,
484 column = gtk_tree_view_get_column(GTK_TREE_VIEW(cts.tree),
486 gtk_tree_view_column_set_sizing(GTK_TREE_VIEW_COLUMN(column),
487 GTK_TREE_VIEW_COLUMN_AUTOSIZE);
488 g_signal_connect(selection, "changed", G_CALLBACK(prefs_tree_select_cb), NULL);
489 gtk_container_add(GTK_CONTAINER(ct_sb), cts.tree);
490 gtk_widget_show(cts.tree);
492 /* A notebook widget without tabs is used to flip between prefs */
493 prefs_nb = gtk_notebook_new();
494 g_object_set_data(G_OBJECT(prefs_w), E_PREFSW_NOTEBOOK_KEY, prefs_nb);
495 gtk_notebook_set_show_tabs(GTK_NOTEBOOK(prefs_nb), FALSE);
496 gtk_notebook_set_show_border(GTK_NOTEBOOK(prefs_nb), FALSE);
497 gtk_container_add(GTK_CONTAINER(top_hb), prefs_nb);
498 gtk_widget_show(prefs_nb);
502 /* Preferences common for all protocols */
503 g_strlcpy(label_str, "Protocols", MAX_TREE_NODE_NAME_LEN);
504 prefs_nb_page_add(prefs_nb, label_str, protocols_prefs_show(), E_PROTOCOLS_PAGE_KEY);
505 protocols_page = cts.page++;
508 g_strlcpy(label_str, "User Interface", MAX_TREE_NODE_NAME_LEN);
509 prefs_nb_page_add(prefs_nb, label_str, gui_prefs_show(), E_GUI_PAGE_KEY);
510 gui_iter = prefs_tree_page_add(label_str, cts.page, store, NULL);
513 /* GUI layout prefs */
514 g_strlcpy(label_str, "Layout", MAX_TREE_NODE_NAME_LEN);
515 prefs_nb_page_add(prefs_nb, label_str, layout_prefs_show(), E_GUI_LAYOUT_PAGE_KEY);
516 layout_iter = prefs_tree_page_add(label_str, cts.page, store, &gui_iter);
517 layout_page = cts.page++;
519 /* GUI Column prefs */
520 g_strlcpy(label_str, "Columns", MAX_TREE_NODE_NAME_LEN);
521 prefs_nb_page_add(prefs_nb, label_str, column_prefs_show(prefs_w), E_GUI_COLUMN_PAGE_KEY);
522 columns_iter = prefs_tree_page_add(label_str, cts.page, store, &gui_iter);
523 columns_page = cts.page++;
526 g_strlcpy(label_str, "Font", MAX_TREE_NODE_NAME_LEN);
527 gui_font_pg = gui_font_prefs_show();
528 prefs_nb_page_add(prefs_nb, label_str, gui_font_pg, E_GUI_FONT_PAGE_KEY);
529 prefs_tree_page_add(label_str, cts.page, store, &gui_iter);
532 gtk_container_set_border_width( GTK_CONTAINER(gui_font_pg), 5 );
534 /* IMPORTANT: the following gtk_font_selection_set_font_name() function will
535 only work if the widget and it's corresponding window is already shown
536 (so don't put the following into gui_font_prefs_show()) !!! */
538 /* We set the current font now, because setting it appears not to work
539 when run before appending the frame to the notebook. */
541 gtk_font_selection_set_font_name(
542 GTK_FONT_SELECTION(gui_font_pg), prefs.gui_font_name);
544 /* GUI Colors prefs */
545 g_strlcpy(label_str, "Colors", MAX_TREE_NODE_NAME_LEN);
546 prefs_nb_page_add(prefs_nb, label_str, stream_prefs_show(), E_GUI_COLORS_PAGE_KEY);
547 prefs_tree_page_add(label_str, cts.page, store, &gui_iter);
550 /* select the main GUI page as the default page and expand it's children */
551 gtk_tree_selection_select_iter(selection, &gui_iter);
552 /* (expand will only take effect, when at least one child exists) */
553 gtk_tree_view_expand_all(GTK_TREE_VIEW(cts.tree));
557 /* Is WPcap loaded? */
561 g_strlcpy(label_str, "Capture", MAX_TREE_NODE_NAME_LEN);
562 prefs_nb_page_add(prefs_nb, label_str, capture_prefs_show(), E_CAPTURE_PAGE_KEY);
563 prefs_tree_page_add(label_str, cts.page, store, NULL);
568 #endif /* HAVE_LIBPCAP */
571 g_strlcpy(label_str, "Printing", MAX_TREE_NODE_NAME_LEN);
572 prefs_nb_page_add(prefs_nb, label_str, printer_prefs_show(), E_PRINT_PAGE_KEY);
573 prefs_tree_page_add(label_str, cts.page, store, NULL);
576 /* Name resolution prefs */
577 g_strlcpy(label_str, "Name Resolution", MAX_TREE_NODE_NAME_LEN);
578 prefs_nb_page_add(prefs_nb, label_str, nameres_prefs_show(), E_NAMERES_PAGE_KEY);
579 prefs_tree_page_add(label_str, cts.page, store, NULL);
582 /* TAPS player prefs */
583 g_strlcpy(label_str, "Statistics", MAX_TREE_NODE_NAME_LEN);
584 prefs_nb_page_add(prefs_nb, label_str, stats_prefs_show(), E_TAPS_PAGE_KEY);
585 prefs_tree_page_add(label_str, cts.page, store, NULL);
588 /* Registered prefs */
589 cts.notebook = prefs_nb;
590 cts.is_protocol = FALSE;
591 prefs_modules_foreach_submodules(NULL, module_prefs_show, &cts);
593 /* Button row: OK and alike buttons */
594 bbox = dlg_button_row_new(GTK_STOCK_HELP, GTK_STOCK_OK, GTK_STOCK_APPLY, GTK_STOCK_SAVE, GTK_STOCK_CANCEL, NULL);
595 gtk_box_pack_start(GTK_BOX(cts.main_vb), bbox, FALSE, FALSE, 0);
596 gtk_widget_show(bbox);
598 ok_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_OK);
599 g_signal_connect(ok_bt, "clicked", G_CALLBACK(prefs_main_ok_cb), prefs_w);
601 apply_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_APPLY);
602 g_signal_connect(apply_bt, "clicked", G_CALLBACK(prefs_main_apply_cb), prefs_w);
604 save_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_SAVE);
605 g_signal_connect(save_bt, "clicked", G_CALLBACK(prefs_main_save_cb), prefs_w);
606 g_object_set_data(G_OBJECT(prefs_w), E_PREFSW_SAVE_BT_KEY, save_bt);
608 cancel_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_CANCEL);
609 g_signal_connect(cancel_bt, "clicked", G_CALLBACK(prefs_main_cancel_cb), prefs_w);
610 window_set_cancel_button(prefs_w, cancel_bt, NULL);
612 gtk_widget_grab_default(ok_bt);
614 help_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_HELP);
615 g_signal_connect(help_bt, "clicked", G_CALLBACK(topic_cb), (gpointer)HELP_PREFERENCES_DIALOG);
617 g_signal_connect(prefs_w, "delete_event", G_CALLBACK(prefs_main_delete_event_cb), NULL);
618 g_signal_connect(prefs_w, "destroy", G_CALLBACK(prefs_main_destroy_cb), prefs_w);
620 gtk_widget_show(prefs_w);
622 /* hide the Save button if the user uses implicit save */
623 if(!prefs.gui_use_pref_save) {
624 gtk_widget_hide(save_bt);
627 window_present(prefs_w);
629 switch (prefs_page) {
630 case PREFS_PAGE_LAYOUT:
631 gtk_tree_selection_select_iter(selection, &layout_iter);
632 gtk_notebook_set_current_page(g_object_get_data(G_OBJECT(prefs_w), E_PREFSW_NOTEBOOK_KEY), layout_page);
634 case PREFS_PAGE_COLUMNS:
635 gtk_tree_selection_select_iter(selection, &columns_iter);
636 gtk_notebook_set_current_page(g_object_get_data(G_OBJECT(prefs_w), E_PREFSW_NOTEBOOK_KEY), columns_page);
639 /* Not implemented yet */
643 g_object_unref(G_OBJECT(store));
647 set_option_label(GtkWidget *main_tb, int table_position,
648 const gchar *label_text, const gchar *tooltip_text)
651 GtkWidget *event_box;
653 label = gtk_label_new(label_text);
654 gtk_misc_set_alignment(GTK_MISC(label), 1.0f, 0.5f);
655 gtk_widget_show(label);
657 event_box = gtk_event_box_new();
658 gtk_event_box_set_visible_window (GTK_EVENT_BOX(event_box), FALSE);
659 gtk_table_attach_defaults(GTK_TABLE(main_tb), event_box, 0, 1,
660 table_position, table_position + 1);
661 if (tooltip_text != NULL)
662 gtk_widget_set_tooltip_text(event_box, tooltip_text);
663 gtk_container_add(GTK_CONTAINER(event_box), label);
664 gtk_widget_show(event_box);
668 create_preference_check_button(GtkWidget *main_tb, int table_position,
669 const gchar *label_text, const gchar *tooltip_text, gboolean active)
671 GtkWidget *check_box;
673 set_option_label(main_tb, table_position, label_text, tooltip_text);
675 check_box = gtk_check_button_new();
676 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check_box), active);
677 gtk_table_attach_defaults(GTK_TABLE(main_tb), check_box, 1, 2,
678 table_position, table_position + 1);
679 if (tooltip_text != NULL)
680 gtk_widget_set_tooltip_text(check_box, tooltip_text);
686 create_preference_radio_buttons(GtkWidget *main_tb, int table_position,
687 const gchar *label_text, const gchar *tooltip_text,
688 const enum_val_t *enumvals, gint current_val)
690 GtkWidget *radio_button_hbox, *button = NULL;
693 const enum_val_t *enum_valp;
694 GtkWidget *event_box;
696 set_option_label(main_tb, table_position, label_text, tooltip_text);
698 radio_button_hbox = gtk_hbox_new(FALSE, 0);
700 for (enum_valp = enumvals, idx = 0; enum_valp->name != NULL;
701 enum_valp++, idx++) {
702 button = gtk_radio_button_new_with_label(rb_group,
703 enum_valp->description);
704 gtk_widget_show(button);
705 rb_group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(button));
706 gtk_box_pack_start(GTK_BOX(radio_button_hbox), button, FALSE,
708 if (enum_valp->value == current_val) {
709 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button),
713 gtk_widget_show(radio_button_hbox);
715 event_box = gtk_event_box_new();
716 gtk_event_box_set_visible_window (GTK_EVENT_BOX(event_box), FALSE);
717 gtk_container_add(GTK_CONTAINER(event_box), radio_button_hbox);
718 gtk_table_attach_defaults(GTK_TABLE(main_tb), event_box, 1, 2,
719 table_position, table_position+1);
720 if (tooltip_text != NULL)
721 gtk_widget_set_tooltip_text(event_box, tooltip_text);
722 gtk_widget_show(event_box);
725 * It doesn't matter which of the buttons we return - we fetch
726 * the value by looking at the entire radio button group to
727 * which it belongs, and we can get that from any button.
733 label_to_enum_val(GtkWidget *label, const enum_val_t *enumvals)
735 const gchar *label_string;
738 /* Get the label's text, and translate it to a value.
739 We match only the descriptions, as those are what appear in
740 the option menu items or as labels for radio buttons.
741 We fail if we don't find a match, as that "can't happen". */
742 label_string = gtk_label_get_text(GTK_LABEL(label));
744 for (i = 0; enumvals[i].name != NULL; i++) {
745 if (g_ascii_strcasecmp(label_string, enumvals[i].description) == 0) {
746 return enumvals[i].value;
749 g_assert_not_reached();
754 fetch_preference_radio_buttons_val(GtkWidget *button,
755 const enum_val_t *enumvals)
761 * Go through the list of of radio buttons in the button's group,
762 * and find the first one that's active.
764 rb_group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(button));
766 for (rb_entry = rb_group; rb_entry != NULL;
767 rb_entry = g_slist_next(rb_entry)) {
768 button = rb_entry->data;
769 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button)))
773 /* OK, now return the value corresponding to that button's label. */
774 return label_to_enum_val(gtk_bin_get_child(GTK_BIN(button)), enumvals);
778 create_preference_option_menu(GtkWidget *main_tb, int table_position,
779 const gchar *label_text, const gchar *tooltip_text,
780 const enum_val_t *enumvals, gint current_val)
782 GtkWidget *menu_box, *combo_box;
784 const enum_val_t *enum_valp;
785 GtkWidget *event_box;
787 set_option_label(main_tb, table_position, label_text, tooltip_text);
789 /* Create a menu from the enumvals */
790 combo_box = gtk_combo_box_new_text ();
791 if (tooltip_text != NULL)
792 gtk_widget_set_tooltip_text(combo_box, tooltip_text);
794 for (enum_valp = enumvals, idx = 0; enum_valp->name != NULL;
795 enum_valp++, idx++) {
796 gtk_combo_box_append_text (GTK_COMBO_BOX (combo_box), enum_valp->description);
797 if (enum_valp->value == current_val)
800 /* Set the current value active */
801 gtk_combo_box_set_active(GTK_COMBO_BOX(combo_box), menu_idx);
804 * Put the combo box in an hbox, so that it's only as wide
805 * as the widest entry, rather than being as wide as the table
808 menu_box = gtk_hbox_new(FALSE, 0);
809 gtk_box_pack_start(GTK_BOX(menu_box), combo_box, FALSE, FALSE, 0);
811 event_box = gtk_event_box_new();
812 gtk_event_box_set_visible_window (GTK_EVENT_BOX(event_box), FALSE);
813 gtk_table_attach_defaults(GTK_TABLE(main_tb), event_box,
814 1, 2, table_position, table_position + 1);
815 if (tooltip_text != NULL)
816 gtk_widget_set_tooltip_text(event_box, tooltip_text);
817 gtk_container_add(GTK_CONTAINER(event_box), menu_box);
823 fetch_preference_option_menu_val(GtkWidget *combo_box, const enum_val_t *enumvals)
826 * OK, now return the value corresponding to the label for the
827 * currently active entry in the combo box.
831 i = gtk_combo_box_get_active (GTK_COMBO_BOX(combo_box));
833 return enumvals[i].value;
837 create_preference_entry(GtkWidget *main_tb, int table_position,
838 const gchar *label_text, const gchar *tooltip_text, char *value)
842 set_option_label(main_tb, table_position, label_text, tooltip_text);
844 entry = gtk_entry_new();
846 gtk_entry_set_text(GTK_ENTRY(entry), value);
847 gtk_table_attach_defaults(GTK_TABLE(main_tb), entry, 1, 2,
848 table_position, table_position + 1);
849 if (tooltip_text != NULL)
850 gtk_widget_set_tooltip_text(entry, tooltip_text);
851 gtk_widget_show(entry);
857 create_preference_static_text(GtkWidget *main_tb, int table_position,
858 const gchar *label_text, const gchar *tooltip_text)
862 if(label_text != NULL)
863 label = gtk_label_new(label_text);
865 label = gtk_label_new("");
866 gtk_table_attach_defaults(GTK_TABLE(main_tb), label, 0, 2,
867 table_position, table_position + 1);
868 if (tooltip_text != NULL)
869 gtk_widget_set_tooltip_text(label, tooltip_text);
870 gtk_widget_show(label);
876 create_preference_uat(GtkWidget *main_tb, int table_position,
877 const gchar *label_text, const gchar *tooltip_text, void* uat)
879 GtkWidget *button = NULL;
881 set_option_label(main_tb, table_position, label_text, tooltip_text);
883 button = gtk_button_new_from_stock(WIRESHARK_STOCK_EDIT);
885 g_signal_connect(button, "clicked", G_CALLBACK(uat_window_cb), uat);
887 gtk_table_attach_defaults(GTK_TABLE(main_tb), button, 1, 2,
888 table_position, table_position+1);
889 if (tooltip_text != NULL)
890 gtk_widget_set_tooltip_text(button, tooltip_text);
891 gtk_widget_show(button);
898 pref_check(pref_t *pref, gpointer user_data)
902 pref_t **badpref = user_data;
904 /* Fetch the value of the preference, and check whether it's valid. */
905 switch (pref->type) {
908 str_val = gtk_entry_get_text(GTK_ENTRY(pref->control));
911 /* XXX: The following ugly hack prevents a gcc warning
912 "ignoring return value of 'strtoul', declared with attribute warn_unused_result"
913 which can occur when using certain gcc configurations (see _FORTIFY_SOURCE).
914 A dummy variable is not used because when using gcc 4.6 with -Wextra a
915 "set but not used [-Wunused-but-set-variable]" warning will occur.
916 TBD: will this hack pass muster with other validators such as Coverity, CLang, & etc
919 "... perhaps either using spin buttons for numeric preferences, or otherwise making
920 it impossible to type something that's not a number into the GUI for those preferences,
921 and thus avoiding the need to check whether it's a valid number, would also be a good idea."
924 if(strtoul(str_val, &p, pref->info.base)){}
925 if (p == str_val || *p != '\0' || errno != 0) {
927 return PREFS_SET_SYNTAX_ERR; /* number was bad */
932 /* Value can't be bad. */
936 /* Value can't be bad. */
940 /* Value can't be bad. */
944 str_val = gtk_entry_get_text(GTK_ENTRY(pref->control));
946 if (strlen(str_val) != 0) {
949 if (range_convert_str(&newrange, str_val, pref->info.max_value) != CVT_NO_ERROR) {
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_get_active(GTK_TOGGLE_BUTTON(pref->control));
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(void)
1098 GtkWidget *decryption_cm;
1099 GtkWidget *decryption_en;
1100 gboolean wireshark_decryption_was_enabled = FALSE;
1101 gboolean airpcap_decryption_was_enabled = FALSE;
1102 gboolean wireshark_decryption_is_now_enabled = FALSE;
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 pref_copy(pref_t *pref, gpointer user_data _U_)
1344 switch (pref->type) {
1347 pref->saved_val.uint = *pref->varp.uint;
1351 pref->saved_val.boolval = *pref->varp.boolp;
1355 pref->saved_val.enumval = *pref->varp.enump;
1359 g_free(pref->saved_val.string);
1360 pref->saved_val.string = g_strdup(*pref->varp.string);
1364 g_free(pref->saved_val.range);
1365 pref->saved_val.range = range_copy(*pref->varp.range);
1368 case PREF_STATIC_TEXT:
1373 g_assert_not_reached();
1380 module_prefs_copy(module_t *module, gpointer user_data _U_)
1382 /* For all preferences in this module, (re)save current value */
1383 prefs_pref_foreach(module, pref_copy, NULL);
1384 return 0; /* continue making copies */
1387 /* Copy prefs to saved values so we can revert to these values */
1388 /* if the user selects Cancel. */
1389 static void prefs_copy(void) {
1390 free_prefs(&saved_prefs);
1391 copy_prefs(&saved_prefs, &prefs);
1392 prefs_modules_foreach(module_prefs_copy, NULL);
1397 prefs_main_write(void)
1403 /* Create the directory that holds personal configuration files, if
1405 if (create_persconffile_dir(&pf_dir_path) == -1) {
1406 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1407 "Can't create directory\n\"%s\"\nfor preferences file: %s.", pf_dir_path,
1409 g_free(pf_dir_path);
1411 /* Write the preferencs out. */
1412 err = write_prefs(&pf_path);
1414 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1415 "Can't open preferences file\n\"%s\": %s.", pf_path,
1423 * Load the Wireshark decryption keys (just set) and save
1424 * the changes to the adapters' registry
1426 airpcap_load_decryption_keys(airpcap_if_list);
1432 prefs_main_ok_cb(GtkWidget *ok_bt _U_, gpointer parent_w)
1434 gboolean must_redissect = FALSE;
1436 if (!prefs_main_fetch_all(parent_w, &must_redissect))
1437 return; /* Errors in some preference setting - already reported */
1439 /* if we don't have a Save button, just save the settings now */
1440 if (!prefs.gui_use_pref_save) {
1444 prefs_main_apply_all(parent_w, must_redissect);
1446 /* Fill in capture options with values from the preferences */
1447 prefs_to_capture_opts();
1450 prefs_airpcap_update();
1453 /* Now destroy the "Preferences" dialog. */
1454 window_destroy(GTK_WIDGET(parent_w));
1456 if (must_redissect) {
1457 /* Redissect all the packets, and re-evaluate the display filter. */
1458 redissect_packets();
1464 prefs_main_apply_cb(GtkWidget *apply_bt _U_, gpointer parent_w)
1466 gboolean must_redissect = FALSE;
1468 if (!prefs_main_fetch_all(parent_w, &must_redissect))
1469 return; /* Errors in some preference setting - already reported */
1471 /* if we don't have a Save button, just save the settings now */
1472 if (!prefs.gui_use_pref_save) {
1474 prefs_copy(); /* save prefs for reverting if Cancel */
1477 prefs_main_apply_all(parent_w, must_redissect);
1479 /* Fill in capture options with values from the preferences */
1480 prefs_to_capture_opts();
1483 prefs_airpcap_update();
1486 if (must_redissect) {
1487 /* Redissect all the packets, and re-evaluate the display filter. */
1488 redissect_packets();
1493 prefs_main_save_cb(GtkWidget *save_bt _U_, gpointer parent_w)
1495 gboolean must_redissect = FALSE;
1497 if (!prefs_main_fetch_all(parent_w, &must_redissect))
1498 return; /* Errors in some preference setting - already reported */
1501 prefs_copy(); /* save prefs for reverting if Cancel */
1503 /* Now apply those preferences.
1504 XXX - should we do this? The user didn't click "OK" or "Apply".
1507 1) by saving the preferences they presumably indicate that they
1510 2) the next time they fire Wireshark up, those preferences will
1513 3) we'd have to buffer "must_redissect" so that if they do
1514 "Apply" after this, we know we have to redissect;
1516 4) we did apply the protocol preferences, at least, in the past. */
1517 prefs_main_apply_all(parent_w, must_redissect);
1519 /* Fill in capture options with values from the preferences */
1520 prefs_to_capture_opts();
1522 if (must_redissect) {
1523 /* Redissect all the packets, and re-evaluate the display filter. */
1524 redissect_packets();
1529 pref_revert(pref_t *pref, gpointer user_data)
1531 gboolean *pref_changed_p = user_data;
1533 /* Revert the preference to its saved value. */
1534 switch (pref->type) {
1537 if (*pref->varp.uint != pref->saved_val.uint) {
1538 *pref_changed_p = TRUE;
1539 *pref->varp.uint = pref->saved_val.uint;
1544 if (*pref->varp.boolp != pref->saved_val.boolval) {
1545 *pref_changed_p = TRUE;
1546 *pref->varp.boolp = pref->saved_val.boolval;
1551 if (*pref->varp.enump != pref->saved_val.enumval) {
1552 *pref_changed_p = TRUE;
1553 *pref->varp.enump = pref->saved_val.enumval;
1558 if (strcmp(*pref->varp.string, pref->saved_val.string) != 0) {
1559 *pref_changed_p = TRUE;
1560 g_free((void *)*pref->varp.string);
1561 *pref->varp.string = g_strdup(pref->saved_val.string);
1566 if (!ranges_are_equal(*pref->varp.range, pref->saved_val.range)) {
1567 *pref_changed_p = TRUE;
1568 g_free(*pref->varp.range);
1569 *pref->varp.range = range_copy(pref->saved_val.range);
1573 case PREF_STATIC_TEXT:
1578 g_assert_not_reached();
1585 module_prefs_revert(module_t *module, gpointer user_data)
1587 gboolean *must_redissect_p = user_data;
1589 /* For all preferences in this module, revert its value to the value
1590 it had when we popped up the Preferences dialog. Find out whether
1591 this changes any of them. */
1592 module->prefs_changed = FALSE; /* assume none of them changed */
1593 prefs_pref_foreach(module, pref_revert, &module->prefs_changed);
1595 /* If any of them changed, indicate that we must redissect and refilter
1596 the current capture (if we have one), as the preference change
1597 could cause packets to be dissected differently. */
1598 if (module->prefs_changed)
1599 *must_redissect_p = TRUE;
1600 return 0; /* keep processing modules */
1603 /* cancel button pressed, revert prefs to saved and exit dialog */
1605 prefs_main_cancel_cb(GtkWidget *cancel_bt _U_, gpointer parent_w)
1607 gboolean must_redissect = FALSE;
1609 /* Free up the current preferences and copy the saved preferences to the
1610 current preferences. */
1612 copy_prefs(&prefs, &saved_prefs);
1613 cfile.cinfo.columns_changed = FALSE; /* [XXX: "columns_changed" should treally be stored in prefs struct ??] */
1615 /* Now revert the registered preferences. */
1616 prefs_modules_foreach(module_prefs_revert, &must_redissect);
1618 /* Now apply the reverted-to preferences. */
1619 prefs_main_apply_all(parent_w, must_redissect);
1621 window_destroy(GTK_WIDGET(parent_w));
1623 if (must_redissect) {
1624 /* Redissect all the packets, and re-evaluate the display filter. */
1625 redissect_packets();
1629 /* Treat this as a cancel, by calling "prefs_main_cancel_cb()" */
1631 prefs_main_delete_event_cb(GtkWidget *prefs_w_lcl, GdkEvent *event _U_,
1632 gpointer user_data _U_)
1634 prefs_main_cancel_cb(NULL, prefs_w_lcl);
1639 /* dialog *is* already destroyed, clean up memory and such */
1641 prefs_main_destroy_cb(GtkWidget *win _U_, gpointer parent_w)
1643 prefs_main_destroy_all(parent_w);
1645 /* Note that we no longer have a "Preferences" dialog box. */
1649 struct properties_data {
1655 module_search_properties(module_t *module, gpointer user_data)
1657 struct properties_data *p = (struct properties_data *)user_data;
1659 /* If this module has the specified title, remember it. */
1660 if (strcmp(module->title, p->title) == 0) {
1662 return 1; /* stops the search */
1665 if(prefs_module_has_submodules(module))
1666 return prefs_modules_foreach_submodules(module, module_search_properties, p);
1672 tree_expand_row(GtkTreeModel *model, GtkTreeView *tree_view, GtkTreeIter *iter)
1677 /* expand the parent first */
1678 if(gtk_tree_model_iter_parent(model, &parent, iter))
1679 tree_expand_row(model, tree_view, &parent);
1681 path = gtk_tree_model_get_path(model, iter);
1682 gtk_tree_view_expand_row(tree_view, path, FALSE);
1683 /*expand_tree(tree_view, &parent, NULL, NULL);*/
1685 gtk_tree_path_free(path);
1688 /* select a node in the tree view */
1689 /* XXX - this is almost 100% copied from byte_view_select() in proto_draw.c,
1690 * find a way to combine both to have a generic function for this */
1692 tree_select_node(GtkWidget *tree, prefs_tree_iter *iter)
1694 GtkTreeIter local_iter = *iter;
1695 GtkTreeView *tree_view = GTK_TREE_VIEW(tree);
1696 GtkTreeModel *model;
1697 GtkTreePath *first_path;
1699 model = gtk_tree_view_get_model(tree_view);
1701 /* Expand our field's row */
1702 first_path = gtk_tree_model_get_path(model, &local_iter);
1704 /* expand from the top down */
1705 tree_expand_row(model, tree_view, &local_iter);
1707 /* select our field's row */
1708 gtk_tree_selection_select_path(gtk_tree_view_get_selection(tree_view),
1711 /* And position the window so the selection is visible.
1712 * Position the selection in the middle of the viewable
1714 gtk_tree_view_scroll_to_cell(tree_view, first_path, NULL, TRUE, 0.5f, 0.0f);
1716 gtk_tree_path_free(first_path);
1720 /* search the corresponding protocol page of the currently selected field */
1722 properties_cb(GtkWidget *w, gpointer dummy)
1724 header_field_info *hfinfo;
1726 struct properties_data p;
1730 module_t *page_module;
1732 if (cfile.finfo_selected == NULL) {
1733 /* There is no field selected */
1737 /* Find the title for the protocol for the selected field. */
1738 hfinfo = cfile.finfo_selected->hfinfo;
1739 if (hfinfo->parent == -1)
1740 title = prefs_get_title_by_name(hfinfo->abbrev);
1742 title = prefs_get_title_by_name(proto_registrar_get_abbrev(hfinfo->parent));
1744 return; /* Couldn't find it. XXX - just crash? "Can't happen"? */
1746 /* Find the module for that protocol by searching for one with that title.
1747 XXX - should we just associate protocols with modules directly? */
1750 prefs_modules_foreach_submodules(protocols_module, module_search_properties,
1752 if (p.module == NULL) {
1753 /* We didn't find it - that protocol probably has no preferences. */
1757 /* Create a preferences window, or pop up an existing one. */
1758 if (prefs_w != NULL) {
1759 reactivate_window(prefs_w);
1764 /* Search all the pages in that window for the one with the specified
1767 (sw = gtk_notebook_get_nth_page(g_object_get_data(G_OBJECT(prefs_w), E_PREFSW_NOTEBOOK_KEY), page_num)) != NULL;
1769 /* Get the frame from the scrollable window */
1770 frame = g_object_get_data(G_OBJECT(sw), E_PAGESW_FRAME_KEY);
1771 /* Get the module for this page (non-protocol prefs don't have one). */
1773 page_module = g_object_get_data(G_OBJECT(frame), E_PAGE_MODULE_KEY);
1774 if (page_module != NULL) {
1775 if (page_module == p.module) {
1777 g_object_get_data(G_OBJECT(prefs_w), E_PREFSW_TREE_KEY),
1778 g_object_get_data(G_OBJECT(frame), E_PAGE_ITER_KEY));
1786 /* Prefs tree selection callback. The node data has been loaded with
1787 the proper notebook page to load. */
1789 prefs_tree_select_cb(GtkTreeSelection *sel, gpointer dummy _U_)
1792 GtkTreeModel *model;
1795 if (gtk_tree_selection_get_selected(sel, &model, &iter))
1797 gtk_tree_model_get(model, &iter, 1, &page, -1);
1799 gtk_notebook_set_current_page(g_object_get_data(G_OBJECT(prefs_w), E_PREFSW_NOTEBOOK_KEY), page);
1810 * indent-tabs-mode: nil
1813 * ex: set shiftwidth=2 tabstop=8 expandtab
1814 * :indentSize=2:tabSize=8:noTabs=true: