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 "ui/simple_dialog.h"
43 #include "ui/gtk/main.h"
44 #include "ui/gtk/prefs_column.h"
45 #include "ui/gtk/prefs_dlg.h"
46 #include "ui/gtk/prefs_filter_expressions.h"
47 #include "ui/gtk/prefs_print.h"
48 #include "ui/gtk/prefs_stream.h"
49 #include "ui/gtk/prefs_gui.h"
50 #include "ui/gtk/prefs_layout.h"
51 #include "ui/gtk/prefs_capture.h"
52 #include "ui/gtk/prefs_nameres.h"
53 #include "ui/gtk/prefs_taps.h"
54 #include "ui/gtk/prefs_protocols.h"
55 #include "ui/gtk/gui_utils.h"
56 #include "ui/gtk/dlg_utils.h"
57 #include "ui/gtk/stock_icons.h"
58 #include "ui/gtk/help_dlg.h"
59 #include "ui/gtk/keys.h"
60 #include "ui/gtk/uat_gui.h"
61 #include "ui/gtk/old-gtk-compat.h"
65 #include "capture-wpcap.h"
69 #include "airpcap_loader.h"
70 #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"
101 #define E_FILTER_EXPRESSIONS_PAGE_KEY "filter_expressions_page"
104 * Keep a static pointer to the current "Preferences" window, if any, so that
105 * if somebody tries to do "Edit:Preferences" while there's already a
106 * "Preferences" window up, we just pop up the existing one, rather than
107 * creating a new one.
109 static GtkWidget *prefs_w;
112 * Save the value of the preferences as of when the preferences dialog
113 * box was first popped up, so we can revert to those values if the
114 * user selects "Cancel".
116 static e_prefs saved_prefs;
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_str_p = 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);
349 /* Add items for each of the preferences */
350 prefs_pref_foreach(module, pref_show, main_tb);
352 /* Associate this module with the page's frame. */
353 g_object_set_data(G_OBJECT(frame), E_PAGE_MODULE_KEY, module);
355 /* Add the page to the notebook */
356 gtk_notebook_append_page(GTK_NOTEBOOK(cts->notebook), main_sw, NULL);
358 /* Attach the page to the tree item */
359 gtk_tree_store_set(model, &iter, 0, label_str, 1, cts->page, -1);
360 g_object_set_data(G_OBJECT(frame), E_PAGE_ITER_KEY, gtk_tree_iter_copy(&iter));
364 /* Show 'em what we got */
365 gtk_widget_show_all(main_sw);
367 /* show the protocols page */
369 gtk_tree_store_set(model, &iter, 0, label_str, 1, protocols_page, -1);
377 #define prefs_tree_iter GtkTreeIter
379 /* add a page to the tree */
380 static prefs_tree_iter
381 prefs_tree_page_add(const gchar *title, gint page_nr,
382 gpointer store, prefs_tree_iter *parent_iter)
384 prefs_tree_iter iter;
386 gtk_tree_store_append(store, &iter, parent_iter);
387 gtk_tree_store_set(store, &iter, 0, title, 1, page_nr, -1);
391 /* add a page to the notebook */
393 prefs_nb_page_add(GtkWidget *notebook, const gchar *title, GtkWidget *page, const char *page_key)
397 frame = gtk_frame_new(title);
398 gtk_widget_show(frame);
400 gtk_container_add(GTK_CONTAINER(frame), page);
401 g_object_set_data(G_OBJECT(prefs_w), page_key, page);
403 gtk_notebook_append_page (GTK_NOTEBOOK(notebook), frame, NULL);
409 /* show the dialog */
411 prefs_cb(GtkWidget *w, gpointer dummy)
413 prefs_page_cb (w, dummy, PREFS_PAGE_USER_INTERFACE);
417 prefs_page_cb(GtkWidget *w _U_, gpointer dummy _U_, PREFS_PAGE_E prefs_page)
419 GtkWidget *top_hb, *bbox, *prefs_nb, *ct_sb,
420 *ok_bt, *apply_bt, *save_bt, *cancel_bt, *help_bt;
421 GtkWidget *gui_font_pg;
422 gchar label_str[MAX_TREE_NODE_NAME_LEN];
423 struct ct_struct cts;
425 GtkTreeSelection *selection;
426 GtkCellRenderer *renderer;
427 GtkTreeViewColumn *column;
429 prefs_tree_iter gui_iter, layout_iter, columns_iter;
430 gint layout_page, columns_page;
433 if (prefs_w != NULL) {
434 /* There's already a "Preferences" dialog box; reactivate it. */
435 reactivate_window(prefs_w);
439 /* Save the current preferences, so we can revert to those values
440 if the user presses "Cancel". */
441 copy_prefs(&saved_prefs, &prefs);
443 prefs_w = dlg_conf_window_new("Wireshark: Preferences");
446 * Unfortunately, we can't arrange that a GtkTable widget wrap an event box
447 * around a table row, so the spacing between the preference item's label
448 * and its control widgets is inactive and the tooltip doesn't pop up when
449 * the mouse is over it.
452 /* Container for each row of widgets */
453 cts.main_vb = gtk_vbox_new(FALSE, 5);
454 gtk_container_set_border_width(GTK_CONTAINER(cts.main_vb), 5);
455 gtk_container_add(GTK_CONTAINER(prefs_w), cts.main_vb);
456 gtk_widget_show(cts.main_vb);
458 /* Top row: Preferences tree and notebook */
459 top_hb = gtk_hbox_new(FALSE, 10);
460 gtk_container_add(GTK_CONTAINER(cts.main_vb), top_hb);
461 gtk_widget_show(top_hb);
463 /* scrolled window on the left for the categories tree */
464 ct_sb = scrolled_window_new(NULL, NULL);
465 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(ct_sb),
467 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(ct_sb),
468 GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
469 gtk_container_add(GTK_CONTAINER(top_hb), ct_sb);
470 gtk_widget_show(ct_sb);
471 g_object_set_data(G_OBJECT(prefs_w), E_PREFSW_SCROLLW_KEY, ct_sb);
473 /* categories tree */
474 store = gtk_tree_store_new(2, G_TYPE_STRING, G_TYPE_INT);
475 cts.tree = tree_view_new(GTK_TREE_MODEL(store));
476 cts.iter.stamp = 0; /* mark this as the toplevel */
477 g_object_set_data(G_OBJECT(prefs_w), E_PREFSW_TREE_KEY, cts.tree);
478 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(cts.tree), FALSE);
479 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(cts.tree));
480 gtk_tree_selection_set_mode(selection, GTK_SELECTION_SINGLE);
481 renderer = gtk_cell_renderer_text_new();
482 col_offset = gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(cts.tree),
483 -1, "Name", renderer,
485 column = gtk_tree_view_get_column(GTK_TREE_VIEW(cts.tree),
487 gtk_tree_view_column_set_sizing(GTK_TREE_VIEW_COLUMN(column),
488 GTK_TREE_VIEW_COLUMN_AUTOSIZE);
489 g_signal_connect(selection, "changed", G_CALLBACK(prefs_tree_select_cb), NULL);
490 gtk_container_add(GTK_CONTAINER(ct_sb), cts.tree);
491 gtk_widget_show(cts.tree);
493 /* A notebook widget without tabs is used to flip between prefs */
494 prefs_nb = gtk_notebook_new();
495 g_object_set_data(G_OBJECT(prefs_w), E_PREFSW_NOTEBOOK_KEY, prefs_nb);
496 gtk_notebook_set_show_tabs(GTK_NOTEBOOK(prefs_nb), FALSE);
497 gtk_notebook_set_show_border(GTK_NOTEBOOK(prefs_nb), FALSE);
498 gtk_container_add(GTK_CONTAINER(top_hb), prefs_nb);
499 gtk_widget_show(prefs_nb);
503 /* Preferences common for all protocols */
504 g_strlcpy(label_str, "Protocols", MAX_TREE_NODE_NAME_LEN);
505 prefs_nb_page_add(prefs_nb, label_str, protocols_prefs_show(), E_PROTOCOLS_PAGE_KEY);
506 protocols_page = cts.page++;
509 g_strlcpy(label_str, "User Interface", MAX_TREE_NODE_NAME_LEN);
510 prefs_nb_page_add(prefs_nb, label_str, gui_prefs_show(), E_GUI_PAGE_KEY);
511 gui_iter = prefs_tree_page_add(label_str, cts.page, store, NULL);
514 /* GUI layout prefs */
515 g_strlcpy(label_str, "Layout", MAX_TREE_NODE_NAME_LEN);
516 prefs_nb_page_add(prefs_nb, label_str, layout_prefs_show(), E_GUI_LAYOUT_PAGE_KEY);
517 layout_iter = prefs_tree_page_add(label_str, cts.page, store, &gui_iter);
518 layout_page = cts.page++;
520 /* GUI Column prefs */
521 g_strlcpy(label_str, "Columns", MAX_TREE_NODE_NAME_LEN);
522 prefs_nb_page_add(prefs_nb, label_str, column_prefs_show(prefs_w), E_GUI_COLUMN_PAGE_KEY);
523 columns_iter = prefs_tree_page_add(label_str, cts.page, store, &gui_iter);
524 columns_page = cts.page++;
527 g_strlcpy(label_str, "Font", MAX_TREE_NODE_NAME_LEN);
528 gui_font_pg = gui_font_prefs_show();
529 prefs_nb_page_add(prefs_nb, label_str, gui_font_pg, E_GUI_FONT_PAGE_KEY);
530 prefs_tree_page_add(label_str, cts.page, store, &gui_iter);
533 gtk_container_set_border_width( GTK_CONTAINER(gui_font_pg), 5 );
535 /* IMPORTANT: the following gtk_font_selection_set_font_name() function will
536 only work if the widget and it's corresponding window is already shown
537 (so don't put the following into gui_font_prefs_show()) !!! */
539 /* We set the current font now, because setting it appears not to work
540 when run before appending the frame to the notebook. */
542 gtk_font_selection_set_font_name(
543 GTK_FONT_SELECTION(gui_font_pg), prefs.gui_font_name);
545 /* GUI Colors prefs */
546 g_strlcpy(label_str, "Colors", MAX_TREE_NODE_NAME_LEN);
547 prefs_nb_page_add(prefs_nb, label_str, stream_prefs_show(), E_GUI_COLORS_PAGE_KEY);
548 prefs_tree_page_add(label_str, cts.page, store, &gui_iter);
551 /* select the main GUI page as the default page and expand it's children */
552 gtk_tree_selection_select_iter(selection, &gui_iter);
553 /* (expand will only take effect, when at least one child exists) */
554 gtk_tree_view_expand_all(GTK_TREE_VIEW(cts.tree));
558 /* Is WPcap loaded? */
562 g_strlcpy(label_str, "Capture", MAX_TREE_NODE_NAME_LEN);
563 prefs_nb_page_add(prefs_nb, label_str, capture_prefs_show(), E_CAPTURE_PAGE_KEY);
564 prefs_tree_page_add(label_str, cts.page, store, NULL);
569 #endif /* HAVE_LIBPCAP */
572 g_strlcpy(label_str, "Printing", MAX_TREE_NODE_NAME_LEN);
573 prefs_nb_page_add(prefs_nb, label_str, printer_prefs_show(), E_PRINT_PAGE_KEY);
574 prefs_tree_page_add(label_str, cts.page, store, NULL);
577 /* Name resolution prefs */
578 g_strlcpy(label_str, "Name Resolution", MAX_TREE_NODE_NAME_LEN);
579 prefs_nb_page_add(prefs_nb, label_str, nameres_prefs_show(), E_NAMERES_PAGE_KEY);
580 prefs_tree_page_add(label_str, cts.page, store, NULL);
583 /* Saved filter prefs */
584 g_strlcpy(label_str, "Filter Expressions", MAX_TREE_NODE_NAME_LEN);
585 prefs_nb_page_add(prefs_nb, label_str, filter_expressions_prefs_show(),
586 E_FILTER_EXPRESSIONS_PAGE_KEY);
587 prefs_tree_page_add(label_str, cts.page, store, NULL);
590 /* TAPS player prefs */
591 g_strlcpy(label_str, "Statistics", MAX_TREE_NODE_NAME_LEN);
592 prefs_nb_page_add(prefs_nb, label_str, stats_prefs_show(), E_TAPS_PAGE_KEY);
593 prefs_tree_page_add(label_str, cts.page, store, NULL);
596 /* Registered prefs */
597 cts.notebook = prefs_nb;
598 cts.is_protocol = FALSE;
599 prefs_modules_foreach_submodules(NULL, module_prefs_show, &cts);
601 /* Button row: OK and alike buttons */
602 bbox = dlg_button_row_new(GTK_STOCK_HELP, GTK_STOCK_OK, GTK_STOCK_APPLY, GTK_STOCK_SAVE, GTK_STOCK_CANCEL, NULL);
603 gtk_box_pack_start(GTK_BOX(cts.main_vb), bbox, FALSE, FALSE, 0);
604 gtk_widget_show(bbox);
606 ok_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_OK);
607 g_signal_connect(ok_bt, "clicked", G_CALLBACK(prefs_main_ok_cb), prefs_w);
609 apply_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_APPLY);
610 g_signal_connect(apply_bt, "clicked", G_CALLBACK(prefs_main_apply_cb), prefs_w);
612 save_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_SAVE);
613 g_signal_connect(save_bt, "clicked", G_CALLBACK(prefs_main_save_cb), prefs_w);
614 g_object_set_data(G_OBJECT(prefs_w), E_PREFSW_SAVE_BT_KEY, save_bt);
616 cancel_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_CANCEL);
617 g_signal_connect(cancel_bt, "clicked", G_CALLBACK(prefs_main_cancel_cb), prefs_w);
618 window_set_cancel_button(prefs_w, cancel_bt, NULL);
620 gtk_widget_grab_default(ok_bt);
622 help_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_HELP);
623 g_signal_connect(help_bt, "clicked", G_CALLBACK(topic_cb), (gpointer)HELP_PREFERENCES_DIALOG);
625 g_signal_connect(prefs_w, "delete_event", G_CALLBACK(prefs_main_delete_event_cb), NULL);
626 g_signal_connect(prefs_w, "destroy", G_CALLBACK(prefs_main_destroy_cb), prefs_w);
628 gtk_widget_show(prefs_w);
630 /* hide the Save button if the user uses implicit save */
631 if(!prefs.gui_use_pref_save) {
632 gtk_widget_hide(save_bt);
635 window_present(prefs_w);
637 switch (prefs_page) {
638 case PREFS_PAGE_LAYOUT:
639 gtk_tree_selection_select_iter(selection, &layout_iter);
640 gtk_notebook_set_current_page(g_object_get_data(G_OBJECT(prefs_w), E_PREFSW_NOTEBOOK_KEY), layout_page);
642 case PREFS_PAGE_COLUMNS:
643 gtk_tree_selection_select_iter(selection, &columns_iter);
644 gtk_notebook_set_current_page(g_object_get_data(G_OBJECT(prefs_w), E_PREFSW_NOTEBOOK_KEY), columns_page);
647 /* Not implemented yet */
651 g_object_unref(G_OBJECT(store));
655 set_option_label(GtkWidget *main_tb, int table_position,
656 const gchar *label_text, const gchar *tooltip_text)
659 GtkWidget *event_box;
661 label = gtk_label_new(label_text);
662 gtk_misc_set_alignment(GTK_MISC(label), 1.0f, 0.5f);
663 gtk_widget_show(label);
665 event_box = gtk_event_box_new();
666 gtk_event_box_set_visible_window (GTK_EVENT_BOX(event_box), FALSE);
667 gtk_table_attach_defaults(GTK_TABLE(main_tb), event_box, 0, 1,
668 table_position, table_position + 1);
669 if (tooltip_text != NULL)
670 gtk_widget_set_tooltip_text(event_box, tooltip_text);
671 gtk_container_add(GTK_CONTAINER(event_box), label);
672 gtk_widget_show(event_box);
676 create_preference_check_button(GtkWidget *main_tb, int table_position,
677 const gchar *label_text, const gchar *tooltip_text, gboolean active)
679 GtkWidget *check_box;
681 set_option_label(main_tb, table_position, label_text, tooltip_text);
683 check_box = gtk_check_button_new();
684 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check_box), active);
685 gtk_table_attach_defaults(GTK_TABLE(main_tb), check_box, 1, 2,
686 table_position, table_position + 1);
687 if (tooltip_text != NULL)
688 gtk_widget_set_tooltip_text(check_box, tooltip_text);
694 create_preference_radio_buttons(GtkWidget *main_tb, int table_position,
695 const gchar *label_text, const gchar *tooltip_text,
696 const enum_val_t *enumvals, gint current_val)
698 GtkWidget *radio_button_hbox, *button = NULL;
701 const enum_val_t *enum_valp;
702 GtkWidget *event_box;
704 set_option_label(main_tb, table_position, label_text, tooltip_text);
706 radio_button_hbox = gtk_hbox_new(FALSE, 0);
708 for (enum_valp = enumvals, idx = 0; enum_valp->name != NULL;
709 enum_valp++, idx++) {
710 button = gtk_radio_button_new_with_label(rb_group,
711 enum_valp->description);
712 gtk_widget_show(button);
713 rb_group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(button));
714 gtk_box_pack_start(GTK_BOX(radio_button_hbox), button, FALSE,
716 if (enum_valp->value == current_val) {
717 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button),
721 gtk_widget_show(radio_button_hbox);
723 event_box = gtk_event_box_new();
724 gtk_event_box_set_visible_window (GTK_EVENT_BOX(event_box), FALSE);
725 gtk_container_add(GTK_CONTAINER(event_box), radio_button_hbox);
726 gtk_table_attach_defaults(GTK_TABLE(main_tb), event_box, 1, 2,
727 table_position, table_position+1);
728 if (tooltip_text != NULL)
729 gtk_widget_set_tooltip_text(event_box, tooltip_text);
730 gtk_widget_show(event_box);
733 * It doesn't matter which of the buttons we return - we fetch
734 * the value by looking at the entire radio button group to
735 * which it belongs, and we can get that from any button.
741 label_to_enum_val(GtkWidget *label, const enum_val_t *enumvals)
743 const gchar *label_string;
746 /* Get the label's text, and translate it to a value.
747 We match only the descriptions, as those are what appear in
748 the option menu items or as labels for radio buttons.
749 We fail if we don't find a match, as that "can't happen". */
750 label_string = gtk_label_get_text(GTK_LABEL(label));
752 for (i = 0; enumvals[i].name != NULL; i++) {
753 if (g_ascii_strcasecmp(label_string, enumvals[i].description) == 0) {
754 return enumvals[i].value;
757 g_assert_not_reached();
762 fetch_preference_radio_buttons_val(GtkWidget *button,
763 const enum_val_t *enumvals)
769 * Go through the list of of radio buttons in the button's group,
770 * and find the first one that's active.
772 rb_group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(button));
774 for (rb_entry = rb_group; rb_entry != NULL;
775 rb_entry = g_slist_next(rb_entry)) {
776 button = rb_entry->data;
777 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button)))
781 /* OK, now return the value corresponding to that button's label. */
782 return label_to_enum_val(gtk_bin_get_child(GTK_BIN(button)), enumvals);
786 create_preference_option_menu(GtkWidget *main_tb, int table_position,
787 const gchar *label_text, const gchar *tooltip_text,
788 const enum_val_t *enumvals, gint current_val)
790 GtkWidget *menu_box, *combo_box;
792 const enum_val_t *enum_valp;
793 GtkWidget *event_box;
795 set_option_label(main_tb, table_position, label_text, tooltip_text);
797 /* Create a menu from the enumvals */
798 combo_box = gtk_combo_box_text_new();
799 if (tooltip_text != NULL)
800 gtk_widget_set_tooltip_text(combo_box, tooltip_text);
802 for (enum_valp = enumvals, idx = 0; enum_valp->name != NULL;
803 enum_valp++, idx++) {
804 gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo_box), enum_valp->description);
805 if (enum_valp->value == current_val)
808 /* Set the current value active */
809 gtk_combo_box_set_active(GTK_COMBO_BOX(combo_box), menu_idx);
812 * Put the combo box in an hbox, so that it's only as wide
813 * as the widest entry, rather than being as wide as the table
816 menu_box = gtk_hbox_new(FALSE, 0);
817 gtk_box_pack_start(GTK_BOX(menu_box), combo_box, FALSE, FALSE, 0);
819 event_box = gtk_event_box_new();
820 gtk_event_box_set_visible_window (GTK_EVENT_BOX(event_box), FALSE);
821 gtk_table_attach_defaults(GTK_TABLE(main_tb), event_box,
822 1, 2, table_position, table_position + 1);
823 if (tooltip_text != NULL)
824 gtk_widget_set_tooltip_text(event_box, tooltip_text);
825 gtk_container_add(GTK_CONTAINER(event_box), menu_box);
831 fetch_preference_option_menu_val(GtkWidget *combo_box, const enum_val_t *enumvals)
834 * OK, now return the value corresponding to the label for the
835 * currently active entry in the combo box.
839 i = gtk_combo_box_get_active (GTK_COMBO_BOX(combo_box));
841 return enumvals[i].value;
845 create_preference_entry(GtkWidget *main_tb, int table_position,
846 const gchar *label_text, const gchar *tooltip_text, char *value)
850 set_option_label(main_tb, table_position, label_text, tooltip_text);
852 entry = gtk_entry_new();
854 gtk_entry_set_text(GTK_ENTRY(entry), value);
855 gtk_table_attach_defaults(GTK_TABLE(main_tb), entry, 1, 2,
856 table_position, table_position + 1);
857 if (tooltip_text != NULL)
858 gtk_widget_set_tooltip_text(entry, tooltip_text);
859 gtk_widget_show(entry);
865 create_preference_static_text(GtkWidget *main_tb, int table_position,
866 const gchar *label_text, const gchar *tooltip_text)
870 if(label_text != NULL)
871 label = gtk_label_new(label_text);
873 label = gtk_label_new("");
874 gtk_table_attach_defaults(GTK_TABLE(main_tb), label, 0, 2,
875 table_position, table_position + 1);
876 if (tooltip_text != NULL)
877 gtk_widget_set_tooltip_text(label, tooltip_text);
878 gtk_widget_show(label);
884 create_preference_uat(GtkWidget *main_tb, int table_position,
885 const gchar *label_text, const gchar *tooltip_text, void* uat)
887 GtkWidget *button = NULL;
889 set_option_label(main_tb, table_position, label_text, tooltip_text);
891 button = gtk_button_new_from_stock(WIRESHARK_STOCK_EDIT);
893 g_signal_connect(button, "clicked", G_CALLBACK(uat_window_cb), uat);
895 gtk_table_attach_defaults(GTK_TABLE(main_tb), button, 1, 2,
896 table_position, table_position+1);
897 if (tooltip_text != NULL)
898 gtk_widget_set_tooltip_text(button, tooltip_text);
899 gtk_widget_show(button);
906 pref_check(pref_t *pref, gpointer user_data)
910 pref_t **badpref = user_data;
912 /* Fetch the value of the preference, and check whether it's valid. */
913 switch (pref->type) {
916 str_val = gtk_entry_get_text(GTK_ENTRY(pref->control));
919 /* XXX: The following ugly hack prevents a gcc warning
920 "ignoring return value of 'strtoul', declared with attribute warn_unused_result"
921 which can occur when using certain gcc configurations (see -D_FORTIFY_SOURCE).
922 A dummy variable is not used because when using gcc 4.6 with -Wextra a
923 "set but not used [-Wunused-but-set-variable]" warning will occur.
924 (Coverity & CLang apparently do not object to this hack).
927 "... perhaps either using spin buttons for numeric preferences, or otherwise making
928 it impossible to type something that's not a number into the GUI for those preferences,
929 and thus avoiding the need to check whether it's a valid number, would also be a good idea."
932 if(strtoul(str_val, &p, pref->info.base)){}
933 if (p == str_val || *p != '\0' || errno != 0) {
935 return PREFS_SET_SYNTAX_ERR; /* number was bad */
940 /* Value can't be bad. */
944 /* Value can't be bad. */
948 /* Value can't be bad. */
952 str_val = gtk_entry_get_text(GTK_ENTRY(pref->control));
954 if (strlen(str_val) != 0) {
957 if (range_convert_str(&newrange, str_val, pref->info.max_value) != CVT_NO_ERROR) {
959 return PREFS_SET_SYNTAX_ERR; /* range was bad */
965 case PREF_STATIC_TEXT:
967 /* Value can't be bad. */
971 g_assert_not_reached();
978 module_prefs_check(module_t *module, gpointer user_data)
980 /* For all preferences in this module, fetch its value from this
981 module's notebook page and check whether it's valid. */
982 return prefs_pref_foreach(module, pref_check, user_data);
986 pref_fetch(pref_t *pref, gpointer user_data)
993 gboolean *pref_changed_p = user_data;
995 /* Fetch the value of the preference, and set the appropriate variable
997 switch (pref->type) {
1000 str_val = gtk_entry_get_text(GTK_ENTRY(pref->control));
1001 uval = strtoul(str_val, &p, pref->info.base);
1003 if (p == value || *p != '\0')
1004 return PREFS_SET_SYNTAX_ERR; /* number was bad */
1006 if (*pref->varp.uint != uval) {
1007 *pref_changed_p = TRUE;
1008 *pref->varp.uint = uval;
1013 bval = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(pref->control));
1014 if (*pref->varp.boolp != bval) {
1015 *pref_changed_p = TRUE;
1016 *pref->varp.boolp = bval;
1021 if (pref->info.enum_info.radio_buttons) {
1022 enumval = fetch_preference_radio_buttons_val(pref->control,
1023 pref->info.enum_info.enumvals);
1025 enumval = fetch_preference_option_menu_val(pref->control,
1026 pref->info.enum_info.enumvals);
1029 if (*pref->varp.enump != enumval) {
1030 *pref_changed_p = TRUE;
1031 *pref->varp.enump = enumval;
1036 str_val = gtk_entry_get_text(GTK_ENTRY(pref->control));
1037 if (strcmp(*pref->varp.string, str_val) != 0) {
1038 *pref_changed_p = TRUE;
1039 g_free((void *)*pref->varp.string);
1040 *pref->varp.string = g_strdup(str_val);
1049 str_val = gtk_entry_get_text(GTK_ENTRY(pref->control));
1050 ret = range_convert_str(&newrange, str_val, pref->info.max_value);
1051 if (ret != CVT_NO_ERROR)
1053 return PREFS_SET_SYNTAX_ERR; /* range was bad */
1055 return 0; /* XXX - should fail */
1058 if (!ranges_are_equal(*pref->varp.range, newrange)) {
1059 *pref_changed_p = TRUE;
1060 g_free(*pref->varp.range);
1061 *pref->varp.range = newrange;
1068 case PREF_STATIC_TEXT:
1073 g_assert_not_reached();
1080 module_prefs_fetch(module_t *module, gpointer user_data)
1082 gboolean *must_redissect_p = user_data;
1084 /* For all preferences in this module, fetch its value from this
1085 module's notebook page. Find out whether any of them changed. */
1086 module->prefs_changed = FALSE; /* assume none of them changed */
1087 prefs_pref_foreach(module, pref_fetch, &module->prefs_changed);
1089 /* If any of them changed, indicate that we must redissect and refilter
1090 the current capture (if we have one), as the preference change
1091 could cause packets to be dissected differently. */
1092 if (module->prefs_changed)
1093 *must_redissect_p = TRUE;
1095 return 0; /* keep fetching module preferences */
1100 * This function is used to apply changes and update the Wireless Toolbar
1101 * whenever we apply some changes to the WEP preferences
1104 prefs_airpcap_update(void)
1106 GtkWidget *decryption_cm;
1108 gboolean wireshark_decryption_was_enabled = FALSE;
1109 gboolean airpcap_decryption_was_enabled = FALSE;
1110 gboolean wireshark_decryption_is_now_enabled = FALSE;
1112 decryption_cm = GTK_WIDGET(g_object_get_data(G_OBJECT(airpcap_tb),AIRPCAP_TOOLBAR_DECRYPTION_KEY));
1114 if (decryption_cm == NULL) {
1118 cur_active = gtk_combo_box_get_active(GTK_COMBO_BOX(decryption_cm));
1120 if (cur_active < 0) {
1124 switch(cur_active) {
1125 /* XXX - Don't use magic numbers here. cf airpcap_dlg.c:on_decryption_mode_cb_changed() */
1126 case 1: /* Wireshark */
1127 wireshark_decryption_was_enabled = TRUE;
1128 airpcap_decryption_was_enabled = FALSE;
1130 case 2: /* Driver */
1131 wireshark_decryption_was_enabled = FALSE;
1132 airpcap_decryption_was_enabled = TRUE;
1135 wireshark_decryption_was_enabled = FALSE;
1136 airpcap_decryption_was_enabled = FALSE;
1140 wireshark_decryption_is_now_enabled = wireshark_decryption_on();
1142 if(wireshark_decryption_is_now_enabled && airpcap_decryption_was_enabled)
1144 set_airpcap_decryption(FALSE);
1145 gtk_combo_box_set_active(GTK_COMBO_BOX(decryption_cm), 1);
1147 if(wireshark_decryption_is_now_enabled && !airpcap_decryption_was_enabled)
1149 set_airpcap_decryption(FALSE);
1150 gtk_combo_box_set_active(GTK_COMBO_BOX(decryption_cm), 1);
1152 else if(!wireshark_decryption_is_now_enabled && wireshark_decryption_was_enabled)
1154 if(airpcap_decryption_was_enabled)
1156 set_airpcap_decryption(TRUE);
1157 gtk_combo_box_set_active(GTK_COMBO_BOX(decryption_cm), 2);
1161 set_airpcap_decryption(FALSE);
1162 gtk_combo_box_set_active(GTK_COMBO_BOX(decryption_cm), 0);
1169 pref_clean(pref_t *pref, gpointer user_data _U_)
1171 switch (pref->type) {
1183 if (pref->saved_val.string != NULL) {
1184 g_free(pref->saved_val.string);
1185 pref->saved_val.string = NULL;
1190 if (pref->saved_val.range != NULL) {
1191 g_free(pref->saved_val.range);
1192 pref->saved_val.range = NULL;
1196 case PREF_STATIC_TEXT:
1201 g_assert_not_reached();
1208 module_prefs_clean(module_t *module, gpointer user_data _U_)
1210 /* For all preferences in this module, clean up any cruft allocated for
1211 use by the GUI code. */
1212 prefs_pref_foreach(module, pref_clean, NULL);
1213 return 0; /* keep cleaning modules */
1216 /* fetch all pref values from all pages */
1218 prefs_main_fetch_all(GtkWidget *dlg, gboolean *must_redissect)
1222 /* First, check that the values are all valid. */
1223 /* XXX - check the non-registered preferences too */
1224 switch (prefs_modules_foreach(module_prefs_check, (gpointer)&badpref)) {
1226 case PREFS_SET_SYNTAX_ERR:
1227 switch (badpref->type) {
1230 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1231 "The value for \"%s\" isn't a valid number.",
1236 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1237 "The value for \"%s\" isn't a valid range.",
1242 g_assert_not_reached();
1247 /* Fetch the preferences (i.e., make sure all the values set in all of
1248 the preferences panes have been copied to "prefs" and the registered
1250 gui_prefs_fetch(g_object_get_data(G_OBJECT(dlg), E_GUI_PAGE_KEY));
1251 layout_prefs_fetch(g_object_get_data(G_OBJECT(dlg), E_GUI_LAYOUT_PAGE_KEY));
1252 column_prefs_fetch(g_object_get_data(G_OBJECT(dlg), E_GUI_COLUMN_PAGE_KEY));
1253 stream_prefs_fetch(g_object_get_data(G_OBJECT(dlg), E_GUI_COLORS_PAGE_KEY));
1257 /* Is WPcap loaded? */
1260 capture_prefs_fetch(g_object_get_data(G_OBJECT(dlg), E_CAPTURE_PAGE_KEY));
1264 #endif /* HAVE_LIBPCAP */
1265 printer_prefs_fetch(g_object_get_data(G_OBJECT(dlg), E_PRINT_PAGE_KEY));
1266 nameres_prefs_fetch(g_object_get_data(G_OBJECT(dlg), E_NAMERES_PAGE_KEY));
1267 filter_expressions_prefs_fetch(g_object_get_data(G_OBJECT(dlg),
1268 E_FILTER_EXPRESSIONS_PAGE_KEY));
1269 stats_prefs_fetch(g_object_get_data(G_OBJECT(dlg), E_TAPS_PAGE_KEY));
1270 protocols_prefs_fetch(g_object_get_data(G_OBJECT(dlg), E_PROTOCOLS_PAGE_KEY));
1271 prefs_modules_foreach(module_prefs_fetch, must_redissect);
1276 /* apply all pref values to the real world */
1278 prefs_main_apply_all(GtkWidget *dlg, gboolean redissect)
1283 * Apply the protocol preferences first - "gui_prefs_apply()" could
1284 * cause redissection, and we have to make sure the protocol
1285 * preference changes have been fully applied.
1289 gui_prefs_apply(g_object_get_data(G_OBJECT(dlg), E_GUI_PAGE_KEY), redissect);
1290 layout_prefs_apply(g_object_get_data(G_OBJECT(dlg), E_GUI_LAYOUT_PAGE_KEY));
1291 column_prefs_apply(g_object_get_data(G_OBJECT(dlg), E_GUI_COLUMN_PAGE_KEY));
1292 stream_prefs_apply(g_object_get_data(G_OBJECT(dlg), E_GUI_COLORS_PAGE_KEY));
1296 /* Is WPcap loaded? */
1299 capture_prefs_apply(g_object_get_data(G_OBJECT(dlg), E_CAPTURE_PAGE_KEY));
1303 #endif /* HAVE_LIBPCAP */
1304 printer_prefs_apply(g_object_get_data(G_OBJECT(dlg), E_PRINT_PAGE_KEY));
1305 nameres_prefs_apply(g_object_get_data(G_OBJECT(dlg), E_NAMERES_PAGE_KEY));
1306 stats_prefs_apply(g_object_get_data(G_OBJECT(dlg), E_TAPS_PAGE_KEY));
1307 protocols_prefs_apply(g_object_get_data(G_OBJECT(dlg), E_PROTOCOLS_PAGE_KEY));
1309 /* show/hide the Save button - depending on setting */
1310 save_bt = g_object_get_data(G_OBJECT(prefs_w), E_PREFSW_SAVE_BT_KEY);
1311 if(prefs.gui_use_pref_save) {
1312 gtk_widget_show(save_bt);
1314 gtk_widget_hide(save_bt);
1319 /* destroy all preferences ressources from all pages */
1321 prefs_main_destroy_all(GtkWidget *dlg)
1327 (frame = gtk_notebook_get_nth_page(g_object_get_data(G_OBJECT(prefs_w), E_PREFSW_NOTEBOOK_KEY), page_num)) != NULL;
1329 if(g_object_get_data(G_OBJECT(frame), E_PAGE_ITER_KEY))
1330 gtk_tree_iter_free(g_object_get_data(G_OBJECT(frame), E_PAGE_ITER_KEY));
1333 gui_prefs_destroy(g_object_get_data(G_OBJECT(dlg), E_GUI_PAGE_KEY));
1334 layout_prefs_destroy(g_object_get_data(G_OBJECT(dlg), E_GUI_LAYOUT_PAGE_KEY));
1335 column_prefs_destroy(g_object_get_data(G_OBJECT(dlg), E_GUI_COLUMN_PAGE_KEY));
1336 stream_prefs_destroy(g_object_get_data(G_OBJECT(dlg), E_GUI_COLORS_PAGE_KEY));
1340 /* Is WPcap loaded? */
1343 capture_prefs_destroy(g_object_get_data(G_OBJECT(dlg), E_CAPTURE_PAGE_KEY));
1347 #endif /* HAVE_LIBPCAP */
1348 printer_prefs_destroy(g_object_get_data(G_OBJECT(dlg), E_PRINT_PAGE_KEY));
1349 nameres_prefs_destroy(g_object_get_data(G_OBJECT(dlg), E_NAMERES_PAGE_KEY));
1350 stats_prefs_destroy(g_object_get_data(G_OBJECT(dlg), E_TAPS_PAGE_KEY));
1352 /* Free up the saved preferences (both for "prefs" and for registered
1354 free_prefs(&saved_prefs);
1355 prefs_modules_foreach(module_prefs_clean, NULL);
1356 protocols_prefs_destroy(g_object_get_data(G_OBJECT(dlg), E_PROTOCOLS_PAGE_KEY));
1361 pref_copy(pref_t *pref, gpointer user_data _U_)
1363 switch (pref->type) {
1366 pref->saved_val.uint = *pref->varp.uint;
1370 pref->saved_val.boolval = *pref->varp.boolp;
1374 pref->saved_val.enumval = *pref->varp.enump;
1378 g_free(pref->saved_val.string);
1379 pref->saved_val.string = g_strdup(*pref->varp.string);
1383 g_free(pref->saved_val.range);
1384 pref->saved_val.range = range_copy(*pref->varp.range);
1387 case PREF_STATIC_TEXT:
1392 g_assert_not_reached();
1399 module_prefs_copy(module_t *module, gpointer user_data _U_)
1401 /* For all preferences in this module, (re)save current value */
1402 prefs_pref_foreach(module, pref_copy, NULL);
1403 return 0; /* continue making copies */
1406 /* Copy prefs to saved values so we can revert to these values */
1407 /* if the user selects Cancel. */
1408 static void prefs_copy(void) {
1409 free_prefs(&saved_prefs);
1410 copy_prefs(&saved_prefs, &prefs);
1411 prefs_modules_foreach(module_prefs_copy, NULL);
1416 prefs_main_write(void)
1422 /* Create the directory that holds personal configuration files, if
1424 if (create_persconffile_dir(&pf_dir_path) == -1) {
1425 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1426 "Can't create directory\n\"%s\"\nfor preferences file: %s.", pf_dir_path,
1428 g_free(pf_dir_path);
1430 /* Write the preferencs out. */
1431 err = write_prefs(&pf_path);
1433 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1434 "Can't open preferences file\n\"%s\": %s.", pf_path,
1442 * Load the Wireshark decryption keys (just set) and save
1443 * the changes to the adapters' registry
1445 airpcap_load_decryption_keys(airpcap_if_list);
1451 prefs_main_ok_cb(GtkWidget *ok_bt _U_, gpointer parent_w)
1453 gboolean must_redissect = FALSE;
1455 if (!prefs_main_fetch_all(parent_w, &must_redissect))
1456 return; /* Errors in some preference setting - already reported */
1458 /* if we don't have a Save button, just save the settings now */
1459 if (!prefs.gui_use_pref_save) {
1463 prefs_main_apply_all(parent_w, must_redissect);
1465 /* Fill in capture options with values from the preferences */
1466 prefs_to_capture_opts();
1469 prefs_airpcap_update();
1472 /* Now destroy the "Preferences" dialog. */
1473 window_destroy(GTK_WIDGET(parent_w));
1475 if (must_redissect) {
1476 /* Redissect all the packets, and re-evaluate the display filter. */
1477 redissect_packets();
1483 prefs_main_apply_cb(GtkWidget *apply_bt _U_, gpointer parent_w)
1485 gboolean must_redissect = FALSE;
1487 if (!prefs_main_fetch_all(parent_w, &must_redissect))
1488 return; /* Errors in some preference setting - already reported */
1490 /* if we don't have a Save button, just save the settings now */
1491 if (!prefs.gui_use_pref_save) {
1493 prefs_copy(); /* save prefs for reverting if Cancel */
1496 prefs_main_apply_all(parent_w, must_redissect);
1498 /* Fill in capture options with values from the preferences */
1499 prefs_to_capture_opts();
1502 prefs_airpcap_update();
1505 if (must_redissect) {
1506 /* Redissect all the packets, and re-evaluate the display filter. */
1507 redissect_packets();
1512 prefs_main_save_cb(GtkWidget *save_bt _U_, gpointer parent_w)
1514 gboolean must_redissect = FALSE;
1516 if (!prefs_main_fetch_all(parent_w, &must_redissect))
1517 return; /* Errors in some preference setting - already reported */
1520 prefs_copy(); /* save prefs for reverting if Cancel */
1522 /* Now apply those preferences.
1523 XXX - should we do this? The user didn't click "OK" or "Apply".
1526 1) by saving the preferences they presumably indicate that they
1529 2) the next time they fire Wireshark up, those preferences will
1532 3) we'd have to buffer "must_redissect" so that if they do
1533 "Apply" after this, we know we have to redissect;
1535 4) we did apply the protocol preferences, at least, in the past. */
1536 prefs_main_apply_all(parent_w, must_redissect);
1538 /* Fill in capture options with values from the preferences */
1539 prefs_to_capture_opts();
1541 if (must_redissect) {
1542 /* Redissect all the packets, and re-evaluate the display filter. */
1543 redissect_packets();
1548 pref_revert(pref_t *pref, gpointer user_data)
1550 gboolean *pref_changed_p = user_data;
1552 /* Revert the preference to its saved value. */
1553 switch (pref->type) {
1556 if (*pref->varp.uint != pref->saved_val.uint) {
1557 *pref_changed_p = TRUE;
1558 *pref->varp.uint = pref->saved_val.uint;
1563 if (*pref->varp.boolp != pref->saved_val.boolval) {
1564 *pref_changed_p = TRUE;
1565 *pref->varp.boolp = pref->saved_val.boolval;
1570 if (*pref->varp.enump != pref->saved_val.enumval) {
1571 *pref_changed_p = TRUE;
1572 *pref->varp.enump = pref->saved_val.enumval;
1577 if (strcmp(*pref->varp.string, pref->saved_val.string) != 0) {
1578 *pref_changed_p = TRUE;
1579 g_free((void *)*pref->varp.string);
1580 *pref->varp.string = g_strdup(pref->saved_val.string);
1585 if (!ranges_are_equal(*pref->varp.range, pref->saved_val.range)) {
1586 *pref_changed_p = TRUE;
1587 g_free(*pref->varp.range);
1588 *pref->varp.range = range_copy(pref->saved_val.range);
1592 case PREF_STATIC_TEXT:
1597 g_assert_not_reached();
1604 module_prefs_revert(module_t *module, gpointer user_data)
1606 gboolean *must_redissect_p = user_data;
1608 /* For all preferences in this module, revert its value to the value
1609 it had when we popped up the Preferences dialog. Find out whether
1610 this changes any of them. */
1611 module->prefs_changed = FALSE; /* assume none of them changed */
1612 prefs_pref_foreach(module, pref_revert, &module->prefs_changed);
1614 /* If any of them changed, indicate that we must redissect and refilter
1615 the current capture (if we have one), as the preference change
1616 could cause packets to be dissected differently. */
1617 if (module->prefs_changed)
1618 *must_redissect_p = TRUE;
1619 return 0; /* keep processing modules */
1622 /* cancel button pressed, revert prefs to saved and exit dialog */
1624 prefs_main_cancel_cb(GtkWidget *cancel_bt _U_, gpointer parent_w)
1626 gboolean must_redissect = FALSE;
1628 /* Free up the current preferences and copy the saved preferences to the
1629 current preferences. */
1631 copy_prefs(&prefs, &saved_prefs);
1632 cfile.cinfo.columns_changed = FALSE; /* [XXX: "columns_changed" should treally be stored in prefs struct ??] */
1634 /* Now revert the registered preferences. */
1635 prefs_modules_foreach(module_prefs_revert, &must_redissect);
1637 /* Now apply the reverted-to preferences. */
1638 prefs_main_apply_all(parent_w, must_redissect);
1640 window_destroy(GTK_WIDGET(parent_w));
1642 if (must_redissect) {
1643 /* Redissect all the packets, and re-evaluate the display filter. */
1644 redissect_packets();
1648 /* Treat this as a cancel, by calling "prefs_main_cancel_cb()" */
1650 prefs_main_delete_event_cb(GtkWidget *prefs_w_lcl, GdkEvent *event _U_,
1651 gpointer user_data _U_)
1653 prefs_main_cancel_cb(NULL, prefs_w_lcl);
1658 /* dialog *is* already destroyed, clean up memory and such */
1660 prefs_main_destroy_cb(GtkWidget *win _U_, gpointer parent_w)
1662 prefs_main_destroy_all(parent_w);
1664 /* Note that we no longer have a "Preferences" dialog box. */
1668 struct properties_data {
1674 module_search_properties(module_t *module, gpointer user_data)
1676 struct properties_data *p = (struct properties_data *)user_data;
1678 /* If this module has the specified title, remember it. */
1679 if (strcmp(module->title, p->title) == 0) {
1681 return 1; /* stops the search */
1684 if(prefs_module_has_submodules(module))
1685 return prefs_modules_foreach_submodules(module, module_search_properties, p);
1691 tree_expand_row(GtkTreeModel *model, GtkTreeView *tree_view, GtkTreeIter *iter)
1696 /* expand the parent first */
1697 if(gtk_tree_model_iter_parent(model, &parent, iter))
1698 tree_expand_row(model, tree_view, &parent);
1700 path = gtk_tree_model_get_path(model, iter);
1701 gtk_tree_view_expand_row(tree_view, path, FALSE);
1702 /*expand_tree(tree_view, &parent, NULL, NULL);*/
1704 gtk_tree_path_free(path);
1707 /* select a node in the tree view */
1708 /* XXX - this is almost 100% copied from byte_view_select() in proto_draw.c,
1709 * find a way to combine both to have a generic function for this */
1711 tree_select_node(GtkWidget *tree, prefs_tree_iter *iter)
1713 GtkTreeIter local_iter = *iter;
1714 GtkTreeView *tree_view = GTK_TREE_VIEW(tree);
1715 GtkTreeModel *model;
1716 GtkTreePath *first_path;
1718 model = gtk_tree_view_get_model(tree_view);
1720 /* Expand our field's row */
1721 first_path = gtk_tree_model_get_path(model, &local_iter);
1723 /* expand from the top down */
1724 tree_expand_row(model, tree_view, &local_iter);
1726 /* select our field's row */
1727 gtk_tree_selection_select_path(gtk_tree_view_get_selection(tree_view),
1730 /* And position the window so the selection is visible.
1731 * Position the selection in the middle of the viewable
1733 gtk_tree_view_scroll_to_cell(tree_view, first_path, NULL, TRUE, 0.5f, 0.0f);
1735 gtk_tree_path_free(first_path);
1739 /* search the corresponding protocol page of the currently selected field */
1741 properties_cb(GtkWidget *w, gpointer dummy)
1743 header_field_info *hfinfo;
1745 struct properties_data p;
1749 module_t *page_module;
1751 if (cfile.finfo_selected == NULL) {
1752 /* There is no field selected */
1756 /* Find the title for the protocol for the selected field. */
1757 hfinfo = cfile.finfo_selected->hfinfo;
1758 if (hfinfo->parent == -1)
1759 title = prefs_get_title_by_name(hfinfo->abbrev);
1761 title = prefs_get_title_by_name(proto_registrar_get_abbrev(hfinfo->parent));
1763 return; /* Couldn't find it. XXX - just crash? "Can't happen"? */
1765 /* Find the module for that protocol by searching for one with that title.
1766 XXX - should we just associate protocols with modules directly? */
1769 prefs_modules_foreach_submodules(protocols_module, module_search_properties,
1771 if (p.module == NULL) {
1772 /* We didn't find it - that protocol probably has no preferences. */
1776 /* Create a preferences window, or pop up an existing one. */
1777 if (prefs_w != NULL) {
1778 reactivate_window(prefs_w);
1783 /* Search all the pages in that window for the one with the specified
1786 (sw = gtk_notebook_get_nth_page(g_object_get_data(G_OBJECT(prefs_w), E_PREFSW_NOTEBOOK_KEY), page_num)) != NULL;
1788 /* Get the frame from the scrollable window */
1789 frame = g_object_get_data(G_OBJECT(sw), E_PAGESW_FRAME_KEY);
1790 /* Get the module for this page (non-protocol prefs don't have one). */
1792 page_module = g_object_get_data(G_OBJECT(frame), E_PAGE_MODULE_KEY);
1793 if (page_module != NULL) {
1794 if (page_module == p.module) {
1796 g_object_get_data(G_OBJECT(prefs_w), E_PREFSW_TREE_KEY),
1797 g_object_get_data(G_OBJECT(frame), E_PAGE_ITER_KEY));
1805 /* Prefs tree selection callback. The node data has been loaded with
1806 the proper notebook page to load. */
1808 prefs_tree_select_cb(GtkTreeSelection *sel, gpointer dummy _U_)
1811 GtkTreeModel *model;
1814 if (gtk_tree_selection_get_selected(sel, &model, &iter))
1816 gtk_tree_model_get(model, &iter, 1, &page, -1);
1818 gtk_notebook_set_current_page(g_object_get_data(G_OBJECT(prefs_w), E_PREFSW_NOTEBOOK_KEY), page);
1829 * indent-tabs-mode: nil
1832 * ex: set shiftwidth=2 tabstop=8 expandtab:
1833 * :indentSize=2:tabSize=8:noTabs=true: