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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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_stream.h"
48 #include "ui/gtk/prefs_gui.h"
49 #include "ui/gtk/prefs_layout.h"
50 #include "ui/gtk/prefs_capture.h"
51 #include "ui/gtk/gui_utils.h"
52 #include "ui/gtk/dlg_utils.h"
53 #include "ui/gtk/stock_icons.h"
54 #include "ui/gtk/help_dlg.h"
55 #include "ui/gtk/keys.h"
56 #include "ui/gtk/uat_gui.h"
57 #include "ui/gtk/old-gtk-compat.h"
58 #include "ui/gtk/file_dlg.h"
62 #include "capture-wpcap.h"
66 #include "airpcap_loader.h"
67 #include "airpcap_gui_utils.h"
71 static void prefs_main_ok_cb(GtkWidget *, gpointer);
72 static void prefs_main_apply_cb(GtkWidget *, gpointer);
73 static void prefs_main_save_cb(GtkWidget *, gpointer);
74 static void prefs_main_cancel_cb(GtkWidget *, gpointer);
75 static gboolean prefs_main_delete_event_cb(GtkWidget *, GdkEvent *, gpointer);
76 static void prefs_main_destroy_cb(GtkWidget *, gpointer);
77 static void prefs_tree_select_cb(GtkTreeSelection *, gpointer);
79 static GtkWidget *create_preference_filename_entry(GtkWidget *, int,
80 const gchar *, const gchar *, char *);
82 #define E_PREFSW_SCROLLW_KEY "prefsw_scrollw"
83 #define E_PREFSW_TREE_KEY "prefsw_tree"
84 #define E_PREFSW_NOTEBOOK_KEY "prefsw_notebook"
85 #define E_PREFSW_SAVE_BT_KEY "prefsw_save_bt"
86 #define E_PAGE_ITER_KEY "page_iter"
87 #define E_PAGE_MODULE_KEY "page_module"
88 #define E_PAGESW_FRAME_KEY "pagesw_frame"
90 #define E_GUI_PAGE_KEY "gui_options_page"
91 #define E_GUI_LAYOUT_PAGE_KEY "gui_layout_page"
92 #define E_GUI_COLUMN_PAGE_KEY "gui_column_options_page"
93 #define E_GUI_FONT_PAGE_KEY "gui_font_options_page"
94 #define E_GUI_COLORS_PAGE_KEY "gui_colors_options_page"
95 #define E_CAPTURE_PAGE_KEY "capture_options_page"
96 #define E_NAMERES_PAGE_KEY "nameres_options_page"
97 #define E_FILTER_EXPRESSIONS_PAGE_KEY "filter_expressions_page"
100 * Keep a static pointer to the current "Preferences" window, if any, so that
101 * if somebody tries to do "Edit:Preferences" while there's already a
102 * "Preferences" window up, we just pop up the existing one, rather than
103 * creating a new one.
105 static GtkWidget *prefs_w;
108 * Save the value of the preferences as of when the preferences dialog
109 * box was first popped up, so we can revert to those values if the
110 * user selects "Cancel".
112 static e_prefs saved_prefs;
123 static gint protocols_page = 0;
126 pref_exists(pref_t *pref _U_, gpointer user_data _U_)
131 /* show a single preference on the GtkTable of a preference page */
133 pref_show(pref_t *pref, gpointer user_data)
135 GtkWidget *main_tb = user_data;
141 /* Give this preference a label which is its title, followed by a colon,
142 and left-align it. */
144 label_len = strlen(title) + 2;
145 label_string = g_malloc(label_len);
146 g_strlcpy(label_string, title, label_len);
149 * Sometimes we don't want to append a ':' after a static text string...
150 * If it is needed, we will specify it in the string itself.
152 if(pref->type != PREF_STATIC_TEXT)
153 g_strlcat(label_string, ":", label_len);
155 /* Save the current value of the preference, so that we can revert it if
156 the user does "Apply" and then "Cancel", and create the control for
157 editing the preference. */
158 switch (pref->type) {
161 pref->saved_val.uint = *pref->varp.uint;
163 /* XXX - there are no uint spinbuttons, so we can't use a spinbutton.
164 Even more annoyingly, even if there were, GLib doesn't define
165 G_MAXUINT - but I think ANSI C may define UINT_MAX, so we could
167 switch (pref->info.base) {
170 g_snprintf(uint_str, sizeof(uint_str), "%u", pref->saved_val.uint);
174 g_snprintf(uint_str, sizeof(uint_str), "%o", pref->saved_val.uint);
178 g_snprintf(uint_str, sizeof(uint_str), "%x", pref->saved_val.uint);
181 pref->control = create_preference_entry(main_tb, pref->ordinal,
182 label_string, pref->description,
187 pref->saved_val.boolval = *pref->varp.boolp;
188 pref->control = create_preference_check_button(main_tb, pref->ordinal,
189 label_string, pref->description,
190 pref->saved_val.boolval);
194 pref->saved_val.enumval = *pref->varp.enump;
195 if (pref->info.enum_info.radio_buttons) {
196 /* Show it as radio buttons. */
197 pref->control = create_preference_radio_buttons(main_tb, pref->ordinal,
198 label_string, pref->description,
199 pref->info.enum_info.enumvals,
200 pref->saved_val.enumval);
202 /* Show it as an option menu. */
203 pref->control = create_preference_option_menu(main_tb, pref->ordinal,
204 label_string, pref->description,
205 pref->info.enum_info.enumvals,
206 pref->saved_val.enumval);
211 g_free(pref->saved_val.string);
212 pref->saved_val.string = g_strdup(*pref->varp.string);
213 pref->control = create_preference_entry(main_tb, pref->ordinal,
214 label_string, pref->description,
215 pref->saved_val.string);
219 g_free(pref->saved_val.string);
220 pref->saved_val.string = g_strdup(*pref->varp.string);
221 pref->control = create_preference_filename_entry(main_tb, pref->ordinal,
224 pref->saved_val.string);
231 g_free(pref->saved_val.range);
232 pref->saved_val.range = range_copy(*pref->varp.range);
233 range_str_p = range_convert_range(*pref->varp.range);
234 pref->control = create_preference_entry(main_tb, pref->ordinal,
235 label_string, pref->description,
240 case PREF_STATIC_TEXT:
242 pref->control = create_preference_static_text(main_tb, pref->ordinal,
243 label_string, pref->description);
249 pref->control = create_preference_uat(main_tb, pref->ordinal,
250 label_string, pref->description,
256 g_assert_not_reached();
259 g_free(label_string);
264 #define prefs_tree_iter GtkTreeIter
266 /* add a page to the tree */
267 static prefs_tree_iter
268 prefs_tree_page_add(const gchar *title, gint page_nr,
269 gpointer store, prefs_tree_iter *parent_iter)
271 prefs_tree_iter iter;
273 gtk_tree_store_append(store, &iter, parent_iter);
274 gtk_tree_store_set(store, &iter, 0, title, 1, page_nr, -1);
278 /* add a page to the notebook */
280 prefs_nb_page_add(GtkWidget *notebook, const gchar *title, GtkWidget *page, const char *page_key)
284 frame = gtk_frame_new(title);
285 gtk_widget_show(frame);
287 gtk_container_add(GTK_CONTAINER(frame), page);
288 g_object_set_data(G_OBJECT(prefs_w), page_key, page);
290 gtk_notebook_append_page (GTK_NOTEBOOK(notebook), frame, NULL);
295 /* create a basic window for preferences */
297 simple_prefs_show(module_t *module)
299 GtkWidget *main_tb, *main_vb, *frame, *main_sw;
301 /* Scrolled window */
302 main_sw = gtk_scrolled_window_new(NULL, NULL);
303 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(main_sw), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
306 frame = gtk_frame_new(module->description);
307 gtk_container_set_border_width(GTK_CONTAINER(frame), 5);
308 gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(main_sw), frame);
309 g_object_set_data(G_OBJECT(main_sw), E_PAGESW_FRAME_KEY, frame);
311 /* Main vertical box */
312 main_vb = ws_gtk_box_new(GTK_ORIENTATION_VERTICAL, 5, FALSE);
313 gtk_container_set_border_width(GTK_CONTAINER(main_vb), 5);
314 gtk_container_add(GTK_CONTAINER(frame), main_vb);
317 main_tb = gtk_table_new(module->numprefs, 2, FALSE);
318 gtk_box_pack_start(GTK_BOX(main_vb), main_tb, FALSE, FALSE, 0);
319 gtk_table_set_row_spacings(GTK_TABLE(main_tb), 10);
320 gtk_table_set_col_spacings(GTK_TABLE(main_tb), 15);
322 /* Add items for each of the preferences */
323 prefs_pref_foreach(module, pref_show, main_tb);
325 /* Show 'em what we got */
326 gtk_widget_show_all(main_vb);
331 #define MAX_TREE_NODE_NAME_LEN 64
333 /* show prefs page for each registered module (protocol) */
335 module_prefs_show(module_t *module, gpointer user_data)
337 struct ct_struct *cts = user_data;
338 struct ct_struct child_cts;
339 GtkWidget *main_vb, *main_tb, *frame, *main_sw;
340 gchar label_str[MAX_TREE_NODE_NAME_LEN];
345 * Is this module a subtree, with modules underneath it?
347 if (!prefs_module_has_submodules(module)) {
350 * Does it have any preferences (other than possibly obsolete ones)?
352 if (prefs_pref_foreach(module, pref_exists, NULL) == 0) {
354 * No. Don't put the module into the preferences window.
355 * XXX - we should do the same for subtrees; if a subtree has
356 * nothing under it that will be displayed, don't put it into
364 * Add this module to the tree.
366 g_strlcpy(label_str, module->title, MAX_TREE_NODE_NAME_LEN);
367 model = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(cts->tree)));
369 if (module->parent == NULL) {
370 prefs_nb_page_add(cts->notebook, label_str, simple_prefs_show(module), module->title);
371 gtk_tree_store_append(model, &iter, NULL);
372 /* Save the protocols page */
373 if (strcmp(module->title, "Protocols") == 0) {
374 protocols_page = cts->page++;
380 gtk_tree_store_append(model, &iter, &cts->iter);
385 if (prefs_module_has_submodules(module)) {
390 gtk_tree_store_set(model, &iter, 0, label_str, 1, -1, -1);
393 * Walk the subtree and attach stuff to it.
396 child_cts.iter = iter;
397 prefs_modules_foreach_submodules(module, module_prefs_show, &child_cts);
399 /* keep the page count right */
400 cts->page = child_cts.page;
405 * Has preferences. Create a notebook page for it.
408 /* Scrolled window */
409 main_sw = gtk_scrolled_window_new(NULL, NULL);
410 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(main_sw), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
413 frame = gtk_frame_new(module->description);
414 gtk_container_set_border_width(GTK_CONTAINER(frame), 5);
415 gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(main_sw), frame);
416 g_object_set_data(G_OBJECT(main_sw), E_PAGESW_FRAME_KEY, frame);
418 /* Main vertical box */
419 main_vb = ws_gtk_box_new(GTK_ORIENTATION_VERTICAL, 5, FALSE);
420 gtk_container_set_border_width(GTK_CONTAINER(main_vb), 5);
421 gtk_container_add(GTK_CONTAINER(frame), main_vb);
424 main_tb = gtk_table_new(module->numprefs, 2, FALSE);
425 gtk_box_pack_start(GTK_BOX(main_vb), main_tb, FALSE, FALSE, 0);
426 gtk_table_set_row_spacings(GTK_TABLE(main_tb), 10);
427 gtk_table_set_col_spacings(GTK_TABLE(main_tb), 15);
429 /* Add items for each of the preferences */
430 prefs_pref_foreach(module, pref_show, main_tb);
432 /* Associate this module with the page's frame. */
433 g_object_set_data(G_OBJECT(frame), E_PAGE_MODULE_KEY, module);
435 /* Add the page to the notebook */
436 gtk_notebook_append_page(GTK_NOTEBOOK(cts->notebook), main_sw, NULL);
438 /* Attach the page to the tree item */
439 gtk_tree_store_set(model, &iter, 0, label_str, 1, cts->page, -1);
440 g_object_set_data(G_OBJECT(frame), E_PAGE_ITER_KEY, gtk_tree_iter_copy(&iter));
444 /* Show 'em what we got */
445 gtk_widget_show_all(main_sw);
447 /* show the protocols page */
449 gtk_tree_store_set(model, &iter, 0, label_str, 1, protocols_page, -1);
457 /* show the dialog */
459 prefs_cb(GtkWidget *w, gpointer dummy)
461 prefs_page_cb (w, dummy, PREFS_PAGE_USER_INTERFACE);
465 prefs_page_cb(GtkWidget *w _U_, gpointer dummy _U_, PREFS_PAGE_E prefs_page)
467 GtkWidget *top_hb, *bbox, *prefs_nb, *ct_sb,
468 *ok_bt, *apply_bt, *save_bt, *cancel_bt, *help_bt;
469 GtkWidget *gui_font_pg;
470 gchar label_str[MAX_TREE_NODE_NAME_LEN];
471 struct ct_struct cts;
473 GtkTreeSelection *selection;
474 GtkCellRenderer *renderer;
475 GtkTreeViewColumn *column;
477 prefs_tree_iter gui_iter, layout_iter, columns_iter;
478 gint layout_page, columns_page;
481 if (prefs_w != NULL) {
482 /* There's already a "Preferences" dialog box; reactivate it. */
483 reactivate_window(prefs_w);
487 /* Save the current preferences, so we can revert to those values
488 if the user presses "Cancel". */
489 copy_prefs(&saved_prefs, &prefs);
491 prefs_w = dlg_conf_window_new("Wireshark: Preferences");
494 * Unfortunately, we can't arrange that a GtkTable widget wrap an event box
495 * around a table row, so the spacing between the preference item's label
496 * and its control widgets is inactive and the tooltip doesn't pop up when
497 * the mouse is over it.
500 /* Container for each row of widgets */
501 cts.main_vb = ws_gtk_box_new(GTK_ORIENTATION_VERTICAL, 5, FALSE);
502 gtk_container_set_border_width(GTK_CONTAINER(cts.main_vb), 5);
503 gtk_container_add(GTK_CONTAINER(prefs_w), cts.main_vb);
504 gtk_widget_show(cts.main_vb);
506 /* Top row: Preferences tree and notebook */
507 top_hb = ws_gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 10, FALSE);
508 gtk_container_add(GTK_CONTAINER(cts.main_vb), top_hb);
509 gtk_widget_show(top_hb);
511 /* scrolled window on the left for the categories tree */
512 ct_sb = scrolled_window_new(NULL, NULL);
513 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(ct_sb),
515 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(ct_sb),
516 GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
517 gtk_container_add(GTK_CONTAINER(top_hb), ct_sb);
518 gtk_widget_show(ct_sb);
519 g_object_set_data(G_OBJECT(prefs_w), E_PREFSW_SCROLLW_KEY, ct_sb);
521 /* categories tree */
522 store = gtk_tree_store_new(2, G_TYPE_STRING, G_TYPE_INT);
523 cts.tree = tree_view_new(GTK_TREE_MODEL(store));
524 cts.iter.stamp = 0; /* mark this as the toplevel */
525 g_object_set_data(G_OBJECT(prefs_w), E_PREFSW_TREE_KEY, cts.tree);
526 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(cts.tree), FALSE);
527 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(cts.tree));
528 gtk_tree_selection_set_mode(selection, GTK_SELECTION_SINGLE);
529 renderer = gtk_cell_renderer_text_new();
530 col_offset = gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(cts.tree),
531 -1, "Name", renderer,
533 column = gtk_tree_view_get_column(GTK_TREE_VIEW(cts.tree),
535 gtk_tree_view_column_set_sizing(GTK_TREE_VIEW_COLUMN(column),
536 GTK_TREE_VIEW_COLUMN_AUTOSIZE);
537 g_signal_connect(selection, "changed", G_CALLBACK(prefs_tree_select_cb), NULL);
538 gtk_container_add(GTK_CONTAINER(ct_sb), cts.tree);
539 gtk_widget_show(cts.tree);
541 /* A notebook widget without tabs is used to flip between prefs */
542 prefs_nb = gtk_notebook_new();
543 g_object_set_data(G_OBJECT(prefs_w), E_PREFSW_NOTEBOOK_KEY, prefs_nb);
544 gtk_notebook_set_show_tabs(GTK_NOTEBOOK(prefs_nb), FALSE);
545 gtk_notebook_set_show_border(GTK_NOTEBOOK(prefs_nb), FALSE);
546 gtk_container_add(GTK_CONTAINER(top_hb), prefs_nb);
547 gtk_widget_show(prefs_nb);
552 g_strlcpy(label_str, "User Interface", MAX_TREE_NODE_NAME_LEN);
553 prefs_nb_page_add(prefs_nb, label_str, gui_prefs_show(), E_GUI_PAGE_KEY);
554 gui_iter = prefs_tree_page_add(label_str, cts.page, store, NULL);
557 /* GUI layout prefs */
558 g_strlcpy(label_str, "Layout", MAX_TREE_NODE_NAME_LEN);
559 prefs_nb_page_add(prefs_nb, label_str, layout_prefs_show(), E_GUI_LAYOUT_PAGE_KEY);
560 layout_iter = prefs_tree_page_add(label_str, cts.page, store, &gui_iter);
561 layout_page = cts.page++;
563 /* GUI Column prefs */
564 g_strlcpy(label_str, "Columns", MAX_TREE_NODE_NAME_LEN);
565 prefs_nb_page_add(prefs_nb, label_str, column_prefs_show(prefs_w), E_GUI_COLUMN_PAGE_KEY);
566 columns_iter = prefs_tree_page_add(label_str, cts.page, store, &gui_iter);
567 columns_page = cts.page++;
570 g_strlcpy(label_str, "Font", MAX_TREE_NODE_NAME_LEN);
571 gui_font_pg = gui_font_prefs_show();
572 prefs_nb_page_add(prefs_nb, label_str, gui_font_pg, E_GUI_FONT_PAGE_KEY);
573 prefs_tree_page_add(label_str, cts.page, store, &gui_iter);
576 gtk_container_set_border_width( GTK_CONTAINER(gui_font_pg), 5 );
578 /* IMPORTANT: the following gtk_font_selection_set_font_name() function will
579 only work if the widget and it's corresponding window is already shown
580 (so don't put the following into gui_font_prefs_show()) !!! */
582 /* We set the current font now, because setting it appears not to work
583 when run before appending the frame to the notebook. */
584 #if GTK_CHECK_VERSION(3,2,0)
585 gtk_font_chooser_set_font(GTK_FONT_CHOOSER(gui_font_pg), prefs.gui_font_name);
587 gtk_font_selection_set_font_name(
588 GTK_FONT_SELECTION(gui_font_pg), prefs.gui_font_name);
589 #endif /* GTK_CHECK_VERSION(3,2,0) */
590 /* GUI Colors prefs */
591 g_strlcpy(label_str, "Colors", MAX_TREE_NODE_NAME_LEN);
592 prefs_nb_page_add(prefs_nb, label_str, stream_prefs_show(), E_GUI_COLORS_PAGE_KEY);
593 prefs_tree_page_add(label_str, cts.page, store, &gui_iter);
596 /* select the main GUI page as the default page and expand it's children */
597 gtk_tree_selection_select_iter(selection, &gui_iter);
598 /* (expand will only take effect, when at least one child exists) */
599 gtk_tree_view_expand_all(GTK_TREE_VIEW(cts.tree));
603 /* Is WPcap loaded? */
607 g_strlcpy(label_str, "Capture", MAX_TREE_NODE_NAME_LEN);
608 prefs_nb_page_add(prefs_nb, label_str, capture_prefs_show(), E_CAPTURE_PAGE_KEY);
609 prefs_tree_page_add(label_str, cts.page, store, NULL);
614 #endif /* HAVE_LIBPCAP */
616 /* Saved filter prefs */
617 g_strlcpy(label_str, "Filter Expressions", MAX_TREE_NODE_NAME_LEN);
618 prefs_nb_page_add(prefs_nb, label_str, filter_expressions_prefs_show(),
619 E_FILTER_EXPRESSIONS_PAGE_KEY);
620 prefs_tree_page_add(label_str, cts.page, store, NULL);
623 /* Registered prefs */
624 cts.notebook = prefs_nb;
626 prefs_modules_foreach_submodules(NULL, module_prefs_show, &cts);
628 /* Button row: OK and alike buttons */
629 bbox = dlg_button_row_new(GTK_STOCK_HELP, GTK_STOCK_OK, GTK_STOCK_APPLY, GTK_STOCK_SAVE, GTK_STOCK_CANCEL, NULL);
630 gtk_box_pack_start(GTK_BOX(cts.main_vb), bbox, FALSE, FALSE, 0);
631 gtk_widget_show(bbox);
633 ok_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_OK);
634 g_signal_connect(ok_bt, "clicked", G_CALLBACK(prefs_main_ok_cb), prefs_w);
636 apply_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_APPLY);
637 g_signal_connect(apply_bt, "clicked", G_CALLBACK(prefs_main_apply_cb), prefs_w);
639 save_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_SAVE);
640 g_signal_connect(save_bt, "clicked", G_CALLBACK(prefs_main_save_cb), prefs_w);
641 g_object_set_data(G_OBJECT(prefs_w), E_PREFSW_SAVE_BT_KEY, save_bt);
643 cancel_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_CANCEL);
644 g_signal_connect(cancel_bt, "clicked", G_CALLBACK(prefs_main_cancel_cb), prefs_w);
645 window_set_cancel_button(prefs_w, cancel_bt, NULL);
647 gtk_widget_grab_default(ok_bt);
649 help_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_HELP);
650 g_signal_connect(help_bt, "clicked", G_CALLBACK(topic_cb), (gpointer)HELP_PREFERENCES_DIALOG);
652 g_signal_connect(prefs_w, "delete_event", G_CALLBACK(prefs_main_delete_event_cb), NULL);
653 g_signal_connect(prefs_w, "destroy", G_CALLBACK(prefs_main_destroy_cb), prefs_w);
655 gtk_widget_show(prefs_w);
657 /* hide the Save button if the user uses implicit save */
658 if(!prefs.gui_use_pref_save) {
659 gtk_widget_hide(save_bt);
662 window_present(prefs_w);
664 switch (prefs_page) {
665 case PREFS_PAGE_LAYOUT:
666 gtk_tree_selection_select_iter(selection, &layout_iter);
667 gtk_notebook_set_current_page(g_object_get_data(G_OBJECT(prefs_w), E_PREFSW_NOTEBOOK_KEY), layout_page);
669 case PREFS_PAGE_COLUMNS:
670 gtk_tree_selection_select_iter(selection, &columns_iter);
671 gtk_notebook_set_current_page(g_object_get_data(G_OBJECT(prefs_w), E_PREFSW_NOTEBOOK_KEY), columns_page);
674 /* Not implemented yet */
678 g_object_unref(G_OBJECT(store));
682 set_option_label(GtkWidget *main_tb, int table_position,
683 const gchar *label_text, const gchar *tooltip_text)
686 GtkWidget *event_box;
688 label = gtk_label_new(label_text);
689 gtk_misc_set_alignment(GTK_MISC(label), 1.0f, 0.5f);
690 gtk_widget_show(label);
692 event_box = gtk_event_box_new();
693 gtk_event_box_set_visible_window (GTK_EVENT_BOX(event_box), FALSE);
694 gtk_table_attach_defaults(GTK_TABLE(main_tb), event_box, 0, 1,
695 table_position, table_position + 1);
696 if (tooltip_text != NULL)
697 gtk_widget_set_tooltip_text(event_box, tooltip_text);
698 gtk_container_add(GTK_CONTAINER(event_box), label);
699 gtk_widget_show(event_box);
703 create_preference_check_button(GtkWidget *main_tb, int table_position,
704 const gchar *label_text, const gchar *tooltip_text, gboolean active)
706 GtkWidget *check_box;
708 set_option_label(main_tb, table_position, label_text, tooltip_text);
710 check_box = gtk_check_button_new();
711 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check_box), active);
712 gtk_table_attach_defaults(GTK_TABLE(main_tb), check_box, 1, 2,
713 table_position, table_position + 1);
714 if (tooltip_text != NULL)
715 gtk_widget_set_tooltip_text(check_box, tooltip_text);
721 create_preference_radio_buttons(GtkWidget *main_tb, int table_position,
722 const gchar *label_text, const gchar *tooltip_text,
723 const enum_val_t *enumvals, gint current_val)
725 GtkWidget *radio_button_hbox, *button = NULL;
728 const enum_val_t *enum_valp;
729 GtkWidget *event_box;
731 set_option_label(main_tb, table_position, label_text, tooltip_text);
733 radio_button_hbox = ws_gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0, FALSE);
735 for (enum_valp = enumvals, idx = 0; enum_valp->name != NULL;
736 enum_valp++, idx++) {
737 button = gtk_radio_button_new_with_label(rb_group,
738 enum_valp->description);
739 gtk_widget_show(button);
740 rb_group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(button));
741 gtk_box_pack_start(GTK_BOX(radio_button_hbox), button, FALSE,
743 if (enum_valp->value == current_val) {
744 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button),
748 gtk_widget_show(radio_button_hbox);
750 event_box = gtk_event_box_new();
751 gtk_event_box_set_visible_window (GTK_EVENT_BOX(event_box), FALSE);
752 gtk_container_add(GTK_CONTAINER(event_box), radio_button_hbox);
753 gtk_table_attach_defaults(GTK_TABLE(main_tb), event_box, 1, 2,
754 table_position, table_position+1);
755 if (tooltip_text != NULL)
756 gtk_widget_set_tooltip_text(event_box, tooltip_text);
757 gtk_widget_show(event_box);
760 * It doesn't matter which of the buttons we return - we fetch
761 * the value by looking at the entire radio button group to
762 * which it belongs, and we can get that from any button.
768 label_to_enum_val(GtkWidget *label, const enum_val_t *enumvals)
770 const gchar *label_string;
773 /* Get the label's text, and translate it to a value.
774 We match only the descriptions, as those are what appear in
775 the option menu items or as labels for radio buttons.
776 We fail if we don't find a match, as that "can't happen". */
777 label_string = gtk_label_get_text(GTK_LABEL(label));
779 for (i = 0; enumvals[i].name != NULL; i++) {
780 if (g_ascii_strcasecmp(label_string, enumvals[i].description) == 0) {
781 return enumvals[i].value;
784 g_assert_not_reached();
789 fetch_preference_radio_buttons_val(GtkWidget *button,
790 const enum_val_t *enumvals)
796 * Go through the list of of radio buttons in the button's group,
797 * and find the first one that's active.
799 rb_group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(button));
801 for (rb_entry = rb_group; rb_entry != NULL;
802 rb_entry = g_slist_next(rb_entry)) {
803 button = rb_entry->data;
804 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button)))
808 /* OK, now return the value corresponding to that button's label. */
809 return label_to_enum_val(gtk_bin_get_child(GTK_BIN(button)), enumvals);
813 create_preference_option_menu(GtkWidget *main_tb, int table_position,
814 const gchar *label_text, const gchar *tooltip_text,
815 const enum_val_t *enumvals, gint current_val)
817 GtkWidget *menu_box, *combo_box;
819 const enum_val_t *enum_valp;
820 GtkWidget *event_box;
822 set_option_label(main_tb, table_position, label_text, tooltip_text);
824 /* Create a menu from the enumvals */
825 combo_box = gtk_combo_box_text_new();
826 if (tooltip_text != NULL)
827 gtk_widget_set_tooltip_text(combo_box, tooltip_text);
829 for (enum_valp = enumvals, idx = 0; enum_valp->name != NULL;
830 enum_valp++, idx++) {
831 gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo_box), enum_valp->description);
832 if (enum_valp->value == current_val)
835 /* Set the current value active */
836 gtk_combo_box_set_active(GTK_COMBO_BOX(combo_box), menu_idx);
839 * Put the combo box in an hbox, so that it's only as wide
840 * as the widest entry, rather than being as wide as the table
843 menu_box = ws_gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0, FALSE);
844 gtk_box_pack_start(GTK_BOX(menu_box), combo_box, FALSE, FALSE, 0);
846 event_box = gtk_event_box_new();
847 gtk_event_box_set_visible_window (GTK_EVENT_BOX(event_box), FALSE);
848 gtk_table_attach_defaults(GTK_TABLE(main_tb), event_box,
849 1, 2, table_position, table_position + 1);
850 if (tooltip_text != NULL)
851 gtk_widget_set_tooltip_text(event_box, tooltip_text);
852 gtk_container_add(GTK_CONTAINER(event_box), menu_box);
858 fetch_preference_option_menu_val(GtkWidget *combo_box, const enum_val_t *enumvals)
861 * OK, now return the value corresponding to the label for the
862 * currently active entry in the combo box.
866 i = gtk_combo_box_get_active (GTK_COMBO_BOX(combo_box));
868 return enumvals[i].value;
872 create_preference_entry(GtkWidget *main_tb, int table_position,
873 const gchar *label_text, const gchar *tooltip_text, char *value)
877 set_option_label(main_tb, table_position, label_text, tooltip_text);
879 entry = gtk_entry_new();
881 gtk_entry_set_text(GTK_ENTRY(entry), value);
882 gtk_table_attach_defaults(GTK_TABLE(main_tb), entry, 1, 2,
883 table_position, table_position + 1);
884 if (tooltip_text != NULL)
885 gtk_widget_set_tooltip_text(entry, tooltip_text);
886 gtk_widget_show(entry);
892 preference_filename_entry_cb(GtkWidget *button, GtkWidget *filename_te)
894 /* XXX - use a better browser dialog title */
895 file_selection_browse(button, filename_te, "Wireshark: file preference",
896 FILE_SELECTION_READ_BROWSE);
900 create_preference_filename_entry(GtkWidget *main_tb, int table_position,
901 const gchar *label_text, const gchar *tooltip_text, char *value)
904 GtkWidget *button, *file_bt_hb;
906 set_option_label(main_tb, table_position, label_text, tooltip_text);
907 file_bt_hb = ws_gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0, FALSE);
908 gtk_table_attach_defaults(GTK_TABLE(main_tb), file_bt_hb, 1, 2,
909 table_position, table_position + 1);
910 gtk_widget_show(file_bt_hb);
912 button = gtk_button_new_from_stock(WIRESHARK_STOCK_BROWSE);
913 gtk_box_pack_end(GTK_BOX(file_bt_hb), button, FALSE, FALSE, 0);
914 gtk_widget_show(button);
916 entry = gtk_entry_new();
917 gtk_box_pack_start(GTK_BOX(file_bt_hb), entry, TRUE, TRUE, 0);
919 gtk_entry_set_text(GTK_ENTRY(entry), value);
920 if (tooltip_text != NULL)
921 gtk_widget_set_tooltip_text(entry, tooltip_text);
922 gtk_widget_show(entry);
924 g_signal_connect(button, "clicked", G_CALLBACK(preference_filename_entry_cb), entry);
931 create_preference_static_text(GtkWidget *main_tb, int table_position,
932 const gchar *label_text, const gchar *tooltip_text)
936 if(label_text != NULL)
937 label = gtk_label_new(label_text);
939 label = gtk_label_new("");
940 gtk_table_attach_defaults(GTK_TABLE(main_tb), label, 0, 2,
941 table_position, table_position + 1);
942 if (tooltip_text != NULL)
943 gtk_widget_set_tooltip_text(label, tooltip_text);
944 gtk_widget_show(label);
950 create_preference_uat(GtkWidget *main_tb, int table_position,
951 const gchar *label_text, const gchar *tooltip_text, void* uat)
955 set_option_label(main_tb, table_position, label_text, tooltip_text);
957 button = gtk_button_new_from_stock(WIRESHARK_STOCK_EDIT);
959 g_signal_connect(button, "clicked", G_CALLBACK(uat_window_cb), uat);
961 gtk_table_attach_defaults(GTK_TABLE(main_tb), button, 1, 2,
962 table_position, table_position+1);
963 if (tooltip_text != NULL)
964 gtk_widget_set_tooltip_text(button, tooltip_text);
965 gtk_widget_show(button);
972 pref_check(pref_t *pref, gpointer user_data)
976 pref_t **badpref = user_data;
978 /* Fetch the value of the preference, and check whether it's valid. */
979 switch (pref->type) {
982 str_val = gtk_entry_get_text(GTK_ENTRY(pref->control));
985 /* XXX: The following ugly hack prevents a gcc warning
986 "ignoring return value of 'strtoul', declared with attribute warn_unused_result"
987 which can occur when using certain gcc configurations (see -D_FORTIFY_SOURCE).
988 A dummy variable is not used because when using gcc 4.6 with -Wextra a
989 "set but not used [-Wunused-but-set-variable]" warning will occur.
990 (Coverity & CLang apparently do not object to this hack).
993 "... perhaps either using spin buttons for numeric preferences, or otherwise making
994 it impossible to type something that's not a number into the GUI for those preferences,
995 and thus avoiding the need to check whether it's a valid number, would also be a good idea."
998 if(strtoul(str_val, &p, pref->info.base)){}
999 if (p == str_val || *p != '\0' || errno != 0) {
1001 return PREFS_SET_SYNTAX_ERR; /* number was bad */
1006 /* Value can't be bad. */
1010 /* Value can't be bad. */
1015 /* Value can't be bad. */
1019 str_val = gtk_entry_get_text(GTK_ENTRY(pref->control));
1021 if (strlen(str_val) != 0) {
1024 if (range_convert_str(&newrange, str_val, pref->info.max_value) != CVT_NO_ERROR) {
1026 return PREFS_SET_SYNTAX_ERR; /* range was bad */
1032 case PREF_STATIC_TEXT:
1034 /* Value can't be bad. */
1038 g_assert_not_reached();
1045 module_prefs_check(module_t *module, gpointer user_data)
1047 /* For all preferences in this module, fetch its value from this
1048 module's notebook page and check whether it's valid. */
1049 return prefs_pref_foreach(module, pref_check, user_data);
1053 pref_fetch(pref_t *pref, gpointer user_data)
1055 const char *str_val;
1060 gboolean *pref_changed_p = user_data;
1062 /* Fetch the value of the preference, and set the appropriate variable
1064 switch (pref->type) {
1067 str_val = gtk_entry_get_text(GTK_ENTRY(pref->control));
1068 uval = strtoul(str_val, &p, pref->info.base);
1070 if (p == value || *p != '\0')
1071 return PREFS_SET_SYNTAX_ERR; /* number was bad */
1073 if (*pref->varp.uint != uval) {
1074 *pref_changed_p = TRUE;
1075 *pref->varp.uint = uval;
1080 bval = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(pref->control));
1081 if (*pref->varp.boolp != bval) {
1082 *pref_changed_p = TRUE;
1083 *pref->varp.boolp = bval;
1088 if (pref->info.enum_info.radio_buttons) {
1089 enumval = fetch_preference_radio_buttons_val(pref->control,
1090 pref->info.enum_info.enumvals);
1092 enumval = fetch_preference_option_menu_val(pref->control,
1093 pref->info.enum_info.enumvals);
1096 if (*pref->varp.enump != enumval) {
1097 *pref_changed_p = TRUE;
1098 *pref->varp.enump = enumval;
1104 str_val = gtk_entry_get_text(GTK_ENTRY(pref->control));
1105 if (strcmp(*pref->varp.string, str_val) != 0) {
1106 *pref_changed_p = TRUE;
1107 g_free((void *)*pref->varp.string);
1108 *pref->varp.string = g_strdup(str_val);
1117 str_val = gtk_entry_get_text(GTK_ENTRY(pref->control));
1118 ret = range_convert_str(&newrange, str_val, pref->info.max_value);
1119 if (ret != CVT_NO_ERROR)
1121 return PREFS_SET_SYNTAX_ERR; /* range was bad */
1123 return 0; /* XXX - should fail */
1126 if (!ranges_are_equal(*pref->varp.range, newrange)) {
1127 *pref_changed_p = TRUE;
1128 g_free(*pref->varp.range);
1129 *pref->varp.range = newrange;
1136 case PREF_STATIC_TEXT:
1141 g_assert_not_reached();
1148 module_prefs_fetch(module_t *module, gpointer user_data)
1150 gboolean *must_redissect_p = user_data;
1152 /* For all preferences in this module, fetch its value from this
1153 module's notebook page. Find out whether any of them changed. */
1154 module->prefs_changed = FALSE; /* assume none of them changed */
1155 prefs_pref_foreach(module, pref_fetch, &module->prefs_changed);
1157 /* If any of them changed, indicate that we must redissect and refilter
1158 the current capture (if we have one), as the preference change
1159 could cause packets to be dissected differently. */
1160 if (module->prefs_changed)
1161 *must_redissect_p = TRUE;
1163 return 0; /* keep fetching module preferences */
1168 * This function is used to apply changes and update the Wireless Toolbar
1169 * whenever we apply some changes to the WEP preferences
1172 prefs_airpcap_update(void)
1174 GtkWidget *decryption_cm;
1176 gboolean wireshark_decryption_was_enabled = FALSE;
1177 gboolean airpcap_decryption_was_enabled = FALSE;
1178 gboolean wireshark_decryption_is_now_enabled = FALSE;
1180 decryption_cm = GTK_WIDGET(g_object_get_data(G_OBJECT(wireless_tb),AIRPCAP_TOOLBAR_DECRYPTION_KEY));
1182 if (decryption_cm == NULL) {
1186 cur_active = gtk_combo_box_get_active(GTK_COMBO_BOX(decryption_cm));
1188 if (cur_active < 0) {
1192 switch(cur_active) {
1193 /* XXX - Don't use magic numbers here. cf airpcap_dlg.c:on_decryption_mode_cb_changed() */
1194 case 1: /* Wireshark */
1195 wireshark_decryption_was_enabled = TRUE;
1196 airpcap_decryption_was_enabled = FALSE;
1198 case 2: /* Driver */
1199 wireshark_decryption_was_enabled = FALSE;
1200 airpcap_decryption_was_enabled = TRUE;
1203 wireshark_decryption_was_enabled = FALSE;
1204 airpcap_decryption_was_enabled = FALSE;
1208 wireshark_decryption_is_now_enabled = wireshark_decryption_on();
1210 if(wireshark_decryption_is_now_enabled && airpcap_decryption_was_enabled)
1212 set_airpcap_decryption(FALSE);
1213 gtk_combo_box_set_active(GTK_COMBO_BOX(decryption_cm), 1);
1215 if(wireshark_decryption_is_now_enabled && !airpcap_decryption_was_enabled)
1217 set_airpcap_decryption(FALSE);
1218 gtk_combo_box_set_active(GTK_COMBO_BOX(decryption_cm), 1);
1220 else if(!wireshark_decryption_is_now_enabled && wireshark_decryption_was_enabled)
1222 if(airpcap_decryption_was_enabled)
1224 set_airpcap_decryption(TRUE);
1225 gtk_combo_box_set_active(GTK_COMBO_BOX(decryption_cm), 2);
1229 set_airpcap_decryption(FALSE);
1230 gtk_combo_box_set_active(GTK_COMBO_BOX(decryption_cm), 0);
1237 pref_clean(pref_t *pref, gpointer user_data _U_)
1239 switch (pref->type) {
1252 if (pref->saved_val.string != NULL) {
1253 g_free(pref->saved_val.string);
1254 pref->saved_val.string = NULL;
1259 if (pref->saved_val.range != NULL) {
1260 g_free(pref->saved_val.range);
1261 pref->saved_val.range = NULL;
1265 case PREF_STATIC_TEXT:
1270 g_assert_not_reached();
1277 module_prefs_clean(module_t *module, gpointer user_data _U_)
1279 /* For all preferences in this module, clean up any cruft allocated for
1280 use by the GUI code. */
1281 prefs_pref_foreach(module, pref_clean, NULL);
1282 return 0; /* keep cleaning modules */
1285 /* fetch all pref values from all pages */
1287 prefs_main_fetch_all(GtkWidget *dlg, gboolean *must_redissect)
1291 /* First, check that the values are all valid. */
1292 /* XXX - check the non-registered preferences too */
1293 switch (prefs_modules_foreach(module_prefs_check, (gpointer)&badpref)) {
1295 case PREFS_SET_SYNTAX_ERR:
1296 switch (badpref->type) {
1299 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1300 "The value for \"%s\" isn't a valid number.",
1305 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1306 "The value for \"%s\" isn't a valid range.",
1311 g_assert_not_reached();
1316 /* Fetch the preferences (i.e., make sure all the values set in all of
1317 the preferences panes have been copied to "prefs" and the registered
1319 gui_prefs_fetch(g_object_get_data(G_OBJECT(dlg), E_GUI_PAGE_KEY));
1320 layout_prefs_fetch(g_object_get_data(G_OBJECT(dlg), E_GUI_LAYOUT_PAGE_KEY));
1321 column_prefs_fetch(g_object_get_data(G_OBJECT(dlg), E_GUI_COLUMN_PAGE_KEY));
1322 stream_prefs_fetch(g_object_get_data(G_OBJECT(dlg), E_GUI_COLORS_PAGE_KEY));
1326 /* Is WPcap loaded? */
1329 capture_prefs_fetch(g_object_get_data(G_OBJECT(dlg), E_CAPTURE_PAGE_KEY));
1333 #endif /* HAVE_LIBPCAP */
1334 filter_expressions_prefs_fetch(g_object_get_data(G_OBJECT(dlg),
1335 E_FILTER_EXPRESSIONS_PAGE_KEY));
1336 prefs_modules_foreach(module_prefs_fetch, must_redissect);
1341 /* apply all pref values to the real world */
1343 prefs_main_apply_all(GtkWidget *dlg, gboolean redissect)
1348 * Apply the protocol preferences first - "gui_prefs_apply()" could
1349 * cause redissection, and we have to make sure the protocol
1350 * preference changes have been fully applied.
1354 gui_prefs_apply(g_object_get_data(G_OBJECT(dlg), E_GUI_PAGE_KEY), redissect);
1355 layout_prefs_apply(g_object_get_data(G_OBJECT(dlg), E_GUI_LAYOUT_PAGE_KEY));
1356 column_prefs_apply(g_object_get_data(G_OBJECT(dlg), E_GUI_COLUMN_PAGE_KEY));
1357 stream_prefs_apply(g_object_get_data(G_OBJECT(dlg), E_GUI_COLORS_PAGE_KEY));
1361 /* Is WPcap loaded? */
1364 capture_prefs_apply(g_object_get_data(G_OBJECT(dlg), E_CAPTURE_PAGE_KEY));
1368 #endif /* HAVE_LIBPCAP */
1370 /* show/hide the Save button - depending on setting */
1371 save_bt = g_object_get_data(G_OBJECT(prefs_w), E_PREFSW_SAVE_BT_KEY);
1372 if(prefs.gui_use_pref_save) {
1373 gtk_widget_show(save_bt);
1375 gtk_widget_hide(save_bt);
1380 /* destroy all preferences ressources from all pages */
1382 prefs_main_destroy_all(GtkWidget *dlg)
1388 (frame = gtk_notebook_get_nth_page(g_object_get_data(G_OBJECT(prefs_w), E_PREFSW_NOTEBOOK_KEY), page_num)) != NULL;
1390 if(g_object_get_data(G_OBJECT(frame), E_PAGE_ITER_KEY))
1391 gtk_tree_iter_free(g_object_get_data(G_OBJECT(frame), E_PAGE_ITER_KEY));
1394 gui_prefs_destroy(g_object_get_data(G_OBJECT(dlg), E_GUI_PAGE_KEY));
1395 layout_prefs_destroy(g_object_get_data(G_OBJECT(dlg), E_GUI_LAYOUT_PAGE_KEY));
1396 column_prefs_destroy(g_object_get_data(G_OBJECT(dlg), E_GUI_COLUMN_PAGE_KEY));
1397 stream_prefs_destroy(g_object_get_data(G_OBJECT(dlg), E_GUI_COLORS_PAGE_KEY));
1401 /* Is WPcap loaded? */
1404 capture_prefs_destroy(g_object_get_data(G_OBJECT(dlg), E_CAPTURE_PAGE_KEY));
1408 #endif /* HAVE_LIBPCAP */
1410 /* Free up the saved preferences (both for "prefs" and for registered
1412 free_prefs(&saved_prefs);
1413 prefs_modules_foreach(module_prefs_clean, NULL);
1418 pref_copy(pref_t *pref, gpointer user_data _U_)
1420 switch (pref->type) {
1423 pref->saved_val.uint = *pref->varp.uint;
1427 pref->saved_val.boolval = *pref->varp.boolp;
1431 pref->saved_val.enumval = *pref->varp.enump;
1436 g_free(pref->saved_val.string);
1437 pref->saved_val.string = g_strdup(*pref->varp.string);
1441 g_free(pref->saved_val.range);
1442 pref->saved_val.range = range_copy(*pref->varp.range);
1445 case PREF_STATIC_TEXT:
1450 g_assert_not_reached();
1457 module_prefs_copy(module_t *module, gpointer user_data _U_)
1459 /* For all preferences in this module, (re)save current value */
1460 prefs_pref_foreach(module, pref_copy, NULL);
1461 return 0; /* continue making copies */
1464 /* Copy prefs to saved values so we can revert to these values */
1465 /* if the user selects Cancel. */
1466 static void prefs_copy(void) {
1467 free_prefs(&saved_prefs);
1468 copy_prefs(&saved_prefs, &prefs);
1469 prefs_modules_foreach(module_prefs_copy, NULL);
1474 prefs_main_write(void)
1480 /* Create the directory that holds personal configuration files, if
1482 if (create_persconffile_dir(&pf_dir_path) == -1) {
1483 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1484 "Can't create directory\n\"%s\"\nfor preferences file: %s.", pf_dir_path,
1486 g_free(pf_dir_path);
1488 /* Write the preferencs out. */
1489 err = write_prefs(&pf_path);
1491 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1492 "Can't open preferences file\n\"%s\": %s.", pf_path,
1500 * Load the Wireshark decryption keys (just set) and save
1501 * the changes to the adapters' registry
1503 airpcap_load_decryption_keys(airpcap_if_list);
1509 prefs_main_ok_cb(GtkWidget *ok_bt _U_, gpointer parent_w)
1511 gboolean must_redissect = FALSE;
1513 if (!prefs_main_fetch_all(parent_w, &must_redissect))
1514 return; /* Errors in some preference setting - already reported */
1516 /* if we don't have a Save button, just save the settings now */
1517 if (!prefs.gui_use_pref_save) {
1521 prefs_main_apply_all(parent_w, must_redissect);
1523 /* Fill in capture options with values from the preferences */
1524 prefs_to_capture_opts();
1527 prefs_airpcap_update();
1530 /* Now destroy the "Preferences" dialog. */
1531 window_destroy(GTK_WIDGET(parent_w));
1533 if (must_redissect) {
1534 /* Redissect all the packets, and re-evaluate the display filter. */
1535 redissect_packets();
1541 prefs_main_apply_cb(GtkWidget *apply_bt _U_, gpointer parent_w)
1543 gboolean must_redissect = FALSE;
1545 if (!prefs_main_fetch_all(parent_w, &must_redissect))
1546 return; /* Errors in some preference setting - already reported */
1548 /* if we don't have a Save button, just save the settings now */
1549 if (!prefs.gui_use_pref_save) {
1551 prefs_copy(); /* save prefs for reverting if Cancel */
1554 prefs_main_apply_all(parent_w, must_redissect);
1556 /* Fill in capture options with values from the preferences */
1557 prefs_to_capture_opts();
1560 prefs_airpcap_update();
1563 if (must_redissect) {
1564 /* Redissect all the packets, and re-evaluate the display filter. */
1565 redissect_packets();
1570 prefs_main_save_cb(GtkWidget *save_bt _U_, gpointer parent_w)
1572 gboolean must_redissect = FALSE;
1574 if (!prefs_main_fetch_all(parent_w, &must_redissect))
1575 return; /* Errors in some preference setting - already reported */
1578 prefs_copy(); /* save prefs for reverting if Cancel */
1580 /* Now apply those preferences.
1581 XXX - should we do this? The user didn't click "OK" or "Apply".
1584 1) by saving the preferences they presumably indicate that they
1587 2) the next time they fire Wireshark up, those preferences will
1590 3) we'd have to buffer "must_redissect" so that if they do
1591 "Apply" after this, we know we have to redissect;
1593 4) we did apply the protocol preferences, at least, in the past. */
1594 prefs_main_apply_all(parent_w, must_redissect);
1596 /* Fill in capture options with values from the preferences */
1597 prefs_to_capture_opts();
1599 if (must_redissect) {
1600 /* Redissect all the packets, and re-evaluate the display filter. */
1601 redissect_packets();
1606 pref_revert(pref_t *pref, gpointer user_data)
1608 gboolean *pref_changed_p = user_data;
1610 /* Revert the preference to its saved value. */
1611 switch (pref->type) {
1614 if (*pref->varp.uint != pref->saved_val.uint) {
1615 *pref_changed_p = TRUE;
1616 *pref->varp.uint = pref->saved_val.uint;
1621 if (*pref->varp.boolp != pref->saved_val.boolval) {
1622 *pref_changed_p = TRUE;
1623 *pref->varp.boolp = pref->saved_val.boolval;
1628 if (*pref->varp.enump != pref->saved_val.enumval) {
1629 *pref_changed_p = TRUE;
1630 *pref->varp.enump = pref->saved_val.enumval;
1636 if (strcmp(*pref->varp.string, pref->saved_val.string) != 0) {
1637 *pref_changed_p = TRUE;
1638 g_free((void *)*pref->varp.string);
1639 *pref->varp.string = g_strdup(pref->saved_val.string);
1644 if (!ranges_are_equal(*pref->varp.range, pref->saved_val.range)) {
1645 *pref_changed_p = TRUE;
1646 g_free(*pref->varp.range);
1647 *pref->varp.range = range_copy(pref->saved_val.range);
1651 case PREF_STATIC_TEXT:
1656 g_assert_not_reached();
1663 module_prefs_revert(module_t *module, gpointer user_data)
1665 gboolean *must_redissect_p = user_data;
1667 /* For all preferences in this module, revert its value to the value
1668 it had when we popped up the Preferences dialog. Find out whether
1669 this changes any of them. */
1670 module->prefs_changed = FALSE; /* assume none of them changed */
1671 prefs_pref_foreach(module, pref_revert, &module->prefs_changed);
1673 /* If any of them changed, indicate that we must redissect and refilter
1674 the current capture (if we have one), as the preference change
1675 could cause packets to be dissected differently. */
1676 if (module->prefs_changed)
1677 *must_redissect_p = TRUE;
1678 return 0; /* keep processing modules */
1681 /* cancel button pressed, revert prefs to saved and exit dialog */
1683 prefs_main_cancel_cb(GtkWidget *cancel_bt _U_, gpointer parent_w)
1685 gboolean must_redissect = FALSE;
1687 /* Free up the current preferences and copy the saved preferences to the
1688 current preferences. */
1690 copy_prefs(&prefs, &saved_prefs);
1691 cfile.cinfo.columns_changed = FALSE; /* [XXX: "columns_changed" should treally be stored in prefs struct ??] */
1693 /* Now revert the registered preferences. */
1694 prefs_modules_foreach(module_prefs_revert, &must_redissect);
1696 /* Now apply the reverted-to preferences. */
1697 prefs_main_apply_all(parent_w, must_redissect);
1699 window_destroy(GTK_WIDGET(parent_w));
1701 if (must_redissect) {
1702 /* Redissect all the packets, and re-evaluate the display filter. */
1703 redissect_packets();
1707 /* Treat this as a cancel, by calling "prefs_main_cancel_cb()" */
1709 prefs_main_delete_event_cb(GtkWidget *prefs_w_lcl, GdkEvent *event _U_,
1710 gpointer user_data _U_)
1712 prefs_main_cancel_cb(NULL, prefs_w_lcl);
1717 /* dialog *is* already destroyed, clean up memory and such */
1719 prefs_main_destroy_cb(GtkWidget *win _U_, gpointer parent_w)
1721 prefs_main_destroy_all(parent_w);
1723 /* Note that we no longer have a "Preferences" dialog box. */
1727 struct properties_data {
1733 module_search_properties(module_t *module, gpointer user_data)
1735 struct properties_data *p = (struct properties_data *)user_data;
1737 /* If this module has the specified title, remember it. */
1738 if (strcmp(module->title, p->title) == 0) {
1740 return 1; /* stops the search */
1743 if(prefs_module_has_submodules(module))
1744 return prefs_modules_foreach_submodules(module, module_search_properties, p);
1750 tree_expand_row(GtkTreeModel *model, GtkTreeView *tree_view, GtkTreeIter *iter)
1755 /* expand the parent first */
1756 if(gtk_tree_model_iter_parent(model, &parent, iter))
1757 tree_expand_row(model, tree_view, &parent);
1759 path = gtk_tree_model_get_path(model, iter);
1760 gtk_tree_view_expand_row(tree_view, path, FALSE);
1761 /*expand_tree(tree_view, &parent, NULL, NULL);*/
1763 gtk_tree_path_free(path);
1766 /* select a node in the tree view */
1767 /* XXX - this is almost 100% copied from byte_view_select() in proto_draw.c,
1768 * find a way to combine both to have a generic function for this */
1770 tree_select_node(GtkWidget *tree, prefs_tree_iter *iter)
1772 GtkTreeIter local_iter = *iter;
1773 GtkTreeView *tree_view = GTK_TREE_VIEW(tree);
1774 GtkTreeModel *model;
1775 GtkTreePath *first_path;
1777 model = gtk_tree_view_get_model(tree_view);
1779 /* Expand our field's row */
1780 first_path = gtk_tree_model_get_path(model, &local_iter);
1782 /* expand from the top down */
1783 tree_expand_row(model, tree_view, &local_iter);
1785 /* select our field's row */
1786 gtk_tree_selection_select_path(gtk_tree_view_get_selection(tree_view),
1789 /* And position the window so the selection is visible.
1790 * Position the selection in the middle of the viewable
1792 gtk_tree_view_scroll_to_cell(tree_view, first_path, NULL, TRUE, 0.5f, 0.0f);
1794 gtk_tree_path_free(first_path);
1798 /* search the corresponding protocol page of the currently selected field */
1800 properties_cb(GtkWidget *w, gpointer dummy)
1802 header_field_info *hfinfo;
1804 struct properties_data p;
1808 module_t *page_module;
1810 if (cfile.finfo_selected == NULL) {
1811 /* There is no field selected */
1815 /* Find the title for the protocol for the selected field. */
1816 hfinfo = cfile.finfo_selected->hfinfo;
1817 if (hfinfo->parent == -1)
1818 title = prefs_get_title_by_name(hfinfo->abbrev);
1820 title = prefs_get_title_by_name(proto_registrar_get_abbrev(hfinfo->parent));
1822 return; /* Couldn't find it. XXX - just crash? "Can't happen"? */
1824 /* Find the module for that protocol by searching for one with that title.
1825 XXX - should we just associate protocols with modules directly? */
1828 prefs_modules_foreach_submodules(protocols_module, module_search_properties,
1830 if (p.module == NULL) {
1831 /* We didn't find it - that protocol probably has no preferences. */
1835 /* Create a preferences window, or pop up an existing one. */
1836 if (prefs_w != NULL) {
1837 reactivate_window(prefs_w);
1842 /* Search all the pages in that window for the one with the specified
1845 (sw = gtk_notebook_get_nth_page(g_object_get_data(G_OBJECT(prefs_w), E_PREFSW_NOTEBOOK_KEY), page_num)) != NULL;
1847 /* Get the frame from the scrollable window */
1848 frame = g_object_get_data(G_OBJECT(sw), E_PAGESW_FRAME_KEY);
1849 /* Get the module for this page (non-protocol prefs don't have one). */
1851 page_module = g_object_get_data(G_OBJECT(frame), E_PAGE_MODULE_KEY);
1852 if (page_module != NULL) {
1853 if (page_module == p.module) {
1855 g_object_get_data(G_OBJECT(prefs_w), E_PREFSW_TREE_KEY),
1856 g_object_get_data(G_OBJECT(frame), E_PAGE_ITER_KEY));
1864 /* Prefs tree selection callback. The node data has been loaded with
1865 the proper notebook page to load. */
1867 prefs_tree_select_cb(GtkTreeSelection *sel, gpointer dummy _U_)
1870 GtkTreeModel *model;
1873 if (gtk_tree_selection_get_selected(sel, &model, &iter))
1875 gtk_tree_model_get(model, &iter, 1, &page, -1);
1877 gtk_notebook_set_current_page(g_object_get_data(G_OBJECT(prefs_w), E_PREFSW_NOTEBOOK_KEY), page);
1888 * indent-tabs-mode: nil
1891 * ex: set shiftwidth=2 tabstop=8 expandtab:
1892 * :indentSize=2:tabSize=8:noTabs=true: