2 * Routines for handling preferences
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
33 #include <epan/filesystem.h>
34 #include <epan/packet.h>
35 #include <epan/prefs.h>
36 #include <epan/strutil.h>
37 #include <epan/prefs-int.h>
41 #include "../simple_dialog.h"
44 #include "gtk/prefs_column.h"
45 #include "gtk/prefs_dlg.h"
46 #include "gtk/prefs_print.h"
47 #include "gtk/prefs_stream.h"
48 #include "gtk/prefs_gui.h"
49 #include "gtk/prefs_layout.h"
50 #include "gtk/prefs_capture.h"
51 #include "gtk/prefs_nameres.h"
52 #include "gtk/prefs_taps.h"
53 #include "gtk/prefs_protocols.h"
54 #include "gtk/gui_utils.h"
55 #include "gtk/dlg_utils.h"
56 #include "gtk/stock_icons.h"
57 #include "gtk/help_dlg.h"
59 #include "gtk/uat_gui.h"
64 #include "capture-wpcap.h"
68 #include "airpcap_loader.h"
69 #include "airpcap_gui_utils.h"
74 static void prefs_main_ok_cb(GtkWidget *, gpointer);
75 static void prefs_main_apply_cb(GtkWidget *, gpointer);
76 static void prefs_main_save_cb(GtkWidget *, gpointer);
77 static void prefs_main_cancel_cb(GtkWidget *, gpointer);
78 static gboolean prefs_main_delete_event_cb(GtkWidget *, GdkEvent *, gpointer);
79 static void prefs_main_destroy_cb(GtkWidget *, gpointer);
80 static void prefs_tree_select_cb(GtkTreeSelection *, gpointer);
83 #define E_PREFSW_SCROLLW_KEY "prefsw_scrollw"
84 #define E_PREFSW_TREE_KEY "prefsw_tree"
85 #define E_PREFSW_NOTEBOOK_KEY "prefsw_notebook"
86 #define E_PREFSW_SAVE_BT_KEY "prefsw_save_bt"
87 #define E_PAGE_ITER_KEY "page_iter"
88 #define E_PAGE_MODULE_KEY "page_module"
89 #define E_PAGESW_FRAME_KEY "pagesw_frame"
91 #define E_GUI_PAGE_KEY "gui_options_page"
92 #define E_GUI_LAYOUT_PAGE_KEY "gui_layout_page"
93 #define E_GUI_COLUMN_PAGE_KEY "gui_column_options_page"
94 #define E_GUI_FONT_PAGE_KEY "gui_font_options_page"
95 #define E_GUI_COLORS_PAGE_KEY "gui_colors_options_page"
96 #define E_CAPTURE_PAGE_KEY "capture_options_page"
97 #define E_PRINT_PAGE_KEY "printer_options_page"
98 #define E_NAMERES_PAGE_KEY "nameres_options_page"
99 #define E_TAPS_PAGE_KEY "taps_options_page"
100 #define E_PROTOCOLS_PAGE_KEY "protocols_options_page"
103 * Keep a static pointer to the current "Preferences" window, if any, so that
104 * if somebody tries to do "Edit:Preferences" while there's already a
105 * "Preferences" window up, we just pop up the existing one, rather than
106 * creating a new one.
108 static GtkWidget *prefs_w;
111 * Save the value of the preferences as of when the preferences dialog
112 * box was first popped up, so we can revert to those values if the
113 * user selects "Cancel".
115 static e_prefs saved_prefs;
122 GtkTooltips *tooltips;
124 gboolean is_protocol;
127 static gint protocols_page = 0;
130 pref_exists(pref_t *pref _U_, gpointer user_data _U_)
135 /* show a single preference on the GtkTable of a preference page */
137 pref_show(pref_t *pref, gpointer user_data)
139 GtkWidget *main_tb = user_data;
145 /* Give this preference a label which is its title, followed by a colon,
146 and left-align it. */
148 label_len = strlen(title) + 2;
149 label_string = g_malloc(label_len);
150 g_strlcpy(label_string, title, label_len);
153 * Sometimes we don't want to append a ':' after a static text string...
154 * If it is needed, we will specify it in the string itself.
156 if(pref->type != PREF_STATIC_TEXT)
157 g_strlcat(label_string, ":", label_len);
159 /* Save the current value of the preference, so that we can revert it if
160 the user does "Apply" and then "Cancel", and create the control for
161 editing the preference. */
162 switch (pref->type) {
165 pref->saved_val.uint = *pref->varp.uint;
167 /* XXX - there are no uint spinbuttons, so we can't use a spinbutton.
168 Even more annoyingly, even if there were, GLib doesn't define
169 G_MAXUINT - but I think ANSI C may define UINT_MAX, so we could
171 switch (pref->info.base) {
174 g_snprintf(uint_str, sizeof(uint_str), "%u", pref->saved_val.uint);
178 g_snprintf(uint_str, sizeof(uint_str), "%o", pref->saved_val.uint);
182 g_snprintf(uint_str, sizeof(uint_str), "%x", pref->saved_val.uint);
185 pref->control = create_preference_entry(main_tb, pref->ordinal,
186 label_string, pref->description,
191 pref->saved_val.boolval = *pref->varp.boolp;
192 pref->control = create_preference_check_button(main_tb, pref->ordinal,
193 label_string, pref->description,
194 pref->saved_val.boolval);
198 pref->saved_val.enumval = *pref->varp.enump;
199 if (pref->info.enum_info.radio_buttons) {
200 /* Show it as radio buttons. */
201 pref->control = create_preference_radio_buttons(main_tb, pref->ordinal,
202 label_string, pref->description,
203 pref->info.enum_info.enumvals,
204 pref->saved_val.enumval);
206 /* Show it as an option menu. */
207 pref->control = create_preference_option_menu(main_tb, pref->ordinal,
208 label_string, pref->description,
209 pref->info.enum_info.enumvals,
210 pref->saved_val.enumval);
215 g_free(pref->saved_val.string);
216 pref->saved_val.string = g_strdup(*pref->varp.string);
217 pref->control = create_preference_entry(main_tb, pref->ordinal,
218 label_string, pref->description,
219 pref->saved_val.string);
226 g_free(pref->saved_val.range);
227 pref->saved_val.range = range_copy(*pref->varp.range);
228 range_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);
348 g_object_set_data(G_OBJECT(main_tb), E_TOOLTIPS_KEY, cts->tooltips);
350 /* Add items for each of the preferences */
351 prefs_pref_foreach(module, pref_show, main_tb);
353 /* Associate this module with the page's frame. */
354 g_object_set_data(G_OBJECT(frame), E_PAGE_MODULE_KEY, module);
356 /* Add the page to the notebook */
357 gtk_notebook_append_page(GTK_NOTEBOOK(cts->notebook), main_sw, NULL);
359 /* Attach the page to the tree item */
360 gtk_tree_store_set(model, &iter, 0, label_str, 1, cts->page, -1);
361 g_object_set_data(G_OBJECT(frame), E_PAGE_ITER_KEY, gtk_tree_iter_copy(&iter));
365 /* Show 'em what we got */
366 gtk_widget_show_all(main_sw);
368 /* show the protocols page */
370 gtk_tree_store_set(model, &iter, 0, label_str, 1, protocols_page, -1);
378 #define prefs_tree_iter GtkTreeIter
380 /* add a page to the tree */
381 static prefs_tree_iter
382 prefs_tree_page_add(const gchar *title, gint page_nr,
383 gpointer store, prefs_tree_iter *parent_iter)
385 prefs_tree_iter iter;
387 gtk_tree_store_append(store, &iter, parent_iter);
388 gtk_tree_store_set(store, &iter, 0, title, 1, page_nr, -1);
392 /* add a page to the notebook */
394 prefs_nb_page_add(GtkWidget *notebook, const gchar *title, GtkWidget *page, const char *page_key)
398 frame = gtk_frame_new(title);
399 gtk_widget_show(frame);
401 gtk_container_add(GTK_CONTAINER(frame), page);
402 g_object_set_data(G_OBJECT(prefs_w), page_key, page);
404 gtk_notebook_append_page (GTK_NOTEBOOK(notebook), frame, NULL);
410 /* show the dialog */
412 prefs_cb(GtkWidget *w, gpointer dummy)
414 prefs_page_cb (w, dummy, PREFS_PAGE_USER_INTERFACE);
418 prefs_page_cb(GtkWidget *w _U_, gpointer dummy _U_, PREFS_PAGE_E prefs_page)
420 GtkWidget *top_hb, *bbox, *prefs_nb, *ct_sb,
421 *ok_bt, *apply_bt, *save_bt, *cancel_bt, *help_bt;
422 GtkWidget *gui_font_pg;
423 gchar label_str[MAX_TREE_NODE_NAME_LEN];
424 struct ct_struct cts;
426 GtkTreeSelection *selection;
427 GtkCellRenderer *renderer;
428 GtkTreeViewColumn *column;
430 prefs_tree_iter gui_iter, layout_iter, columns_iter;
431 gint layout_page, columns_page;
434 if (prefs_w != NULL) {
435 /* There's already a "Preferences" dialog box; reactivate it. */
436 reactivate_window(prefs_w);
440 /* Save the current preferences, so we can revert to those values
441 if the user presses "Cancel". */
442 copy_prefs(&saved_prefs, &prefs);
444 prefs_w = dlg_conf_window_new("Wireshark: Preferences");
447 * Unfortunately, we can't arrange that a GtkTable widget wrap an event box
448 * around a table row, so the spacing between the preference item's label
449 * and its control widgets is inactive and the tooltip doesn't pop up when
450 * the mouse is over it.
452 cts.tooltips = gtk_tooltips_new();
454 /* Container for each row of widgets */
455 cts.main_vb = gtk_vbox_new(FALSE, 5);
456 gtk_container_set_border_width(GTK_CONTAINER(cts.main_vb), 5);
457 gtk_container_add(GTK_CONTAINER(prefs_w), cts.main_vb);
458 gtk_widget_show(cts.main_vb);
460 /* Top row: Preferences tree and notebook */
461 top_hb = gtk_hbox_new(FALSE, 10);
462 gtk_container_add(GTK_CONTAINER(cts.main_vb), top_hb);
463 gtk_widget_show(top_hb);
465 /* scrolled window on the left for the categories tree */
466 ct_sb = scrolled_window_new(NULL, NULL);
467 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(ct_sb),
469 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(ct_sb),
470 GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
471 gtk_container_add(GTK_CONTAINER(top_hb), ct_sb);
472 gtk_widget_show(ct_sb);
473 g_object_set_data(G_OBJECT(prefs_w), E_PREFSW_SCROLLW_KEY, ct_sb);
475 /* categories tree */
476 store = gtk_tree_store_new(2, G_TYPE_STRING, G_TYPE_INT);
477 cts.tree = tree_view_new(GTK_TREE_MODEL(store));
478 cts.iter.stamp = 0; /* mark this as the toplevel */
479 g_object_set_data(G_OBJECT(prefs_w), E_PREFSW_TREE_KEY, cts.tree);
480 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(cts.tree), FALSE);
481 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(cts.tree));
482 gtk_tree_selection_set_mode(selection, GTK_SELECTION_SINGLE);
483 renderer = gtk_cell_renderer_text_new();
484 col_offset = gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(cts.tree),
485 -1, "Name", renderer,
487 column = gtk_tree_view_get_column(GTK_TREE_VIEW(cts.tree),
489 gtk_tree_view_column_set_sizing(GTK_TREE_VIEW_COLUMN(column),
490 GTK_TREE_VIEW_COLUMN_AUTOSIZE);
491 g_signal_connect(selection, "changed", G_CALLBACK(prefs_tree_select_cb), NULL);
492 gtk_container_add(GTK_CONTAINER(ct_sb), cts.tree);
493 gtk_widget_show(cts.tree);
495 /* A notebook widget without tabs is used to flip between prefs */
496 prefs_nb = gtk_notebook_new();
497 g_object_set_data(G_OBJECT(prefs_w), E_PREFSW_NOTEBOOK_KEY, prefs_nb);
498 gtk_notebook_set_show_tabs(GTK_NOTEBOOK(prefs_nb), FALSE);
499 gtk_notebook_set_show_border(GTK_NOTEBOOK(prefs_nb), FALSE);
500 gtk_container_add(GTK_CONTAINER(top_hb), prefs_nb);
501 gtk_widget_show(prefs_nb);
505 /* Preferences common for all protocols */
506 g_strlcpy(label_str, "Protocols", MAX_TREE_NODE_NAME_LEN);
507 prefs_nb_page_add(prefs_nb, label_str, protocols_prefs_show(), E_PROTOCOLS_PAGE_KEY);
508 protocols_page = cts.page++;
511 g_strlcpy(label_str, "User Interface", MAX_TREE_NODE_NAME_LEN);
512 prefs_nb_page_add(prefs_nb, label_str, gui_prefs_show(), E_GUI_PAGE_KEY);
513 gui_iter = prefs_tree_page_add(label_str, cts.page, store, NULL);
516 /* GUI layout prefs */
517 g_strlcpy(label_str, "Layout", MAX_TREE_NODE_NAME_LEN);
518 prefs_nb_page_add(prefs_nb, label_str, layout_prefs_show(), E_GUI_LAYOUT_PAGE_KEY);
519 layout_iter = prefs_tree_page_add(label_str, cts.page, store, &gui_iter);
520 layout_page = cts.page++;
522 /* GUI Column prefs */
523 g_strlcpy(label_str, "Columns", MAX_TREE_NODE_NAME_LEN);
524 prefs_nb_page_add(prefs_nb, label_str, column_prefs_show(prefs_w), E_GUI_COLUMN_PAGE_KEY);
525 columns_iter = prefs_tree_page_add(label_str, cts.page, store, &gui_iter);
526 columns_page = cts.page++;
529 g_strlcpy(label_str, "Font", MAX_TREE_NODE_NAME_LEN);
530 gui_font_pg = gui_font_prefs_show();
531 prefs_nb_page_add(prefs_nb, label_str, gui_font_pg, E_GUI_FONT_PAGE_KEY);
532 prefs_tree_page_add(label_str, cts.page, store, &gui_iter);
535 gtk_container_set_border_width( GTK_CONTAINER(gui_font_pg), 5 );
537 /* IMPORTANT: the following gtk_font_selection_set_font_name() function will
538 only work if the widget and it's corresponding window is already shown
539 (so don't put the following into gui_font_prefs_show()) !!! */
541 /* We set the current font now, because setting it appears not to work
542 when run before appending the frame to the notebook. */
544 gtk_font_selection_set_font_name(
545 GTK_FONT_SELECTION(gui_font_pg), prefs.gui_font_name);
547 /* GUI Colors prefs */
548 g_strlcpy(label_str, "Colors", MAX_TREE_NODE_NAME_LEN);
549 prefs_nb_page_add(prefs_nb, label_str, stream_prefs_show(), E_GUI_COLORS_PAGE_KEY);
550 prefs_tree_page_add(label_str, cts.page, store, &gui_iter);
553 /* select the main GUI page as the default page and expand it's children */
554 gtk_tree_selection_select_iter(selection, &gui_iter);
555 /* (expand will only take effect, when at least one child exists) */
556 gtk_tree_view_expand_all(GTK_TREE_VIEW(cts.tree));
560 /* Is WPcap loaded? */
564 g_strlcpy(label_str, "Capture", MAX_TREE_NODE_NAME_LEN);
565 prefs_nb_page_add(prefs_nb, label_str, capture_prefs_show(), E_CAPTURE_PAGE_KEY);
566 prefs_tree_page_add(label_str, cts.page, store, NULL);
571 #endif /* HAVE_LIBPCAP */
574 g_strlcpy(label_str, "Printing", MAX_TREE_NODE_NAME_LEN);
575 prefs_nb_page_add(prefs_nb, label_str, printer_prefs_show(), E_PRINT_PAGE_KEY);
576 prefs_tree_page_add(label_str, cts.page, store, NULL);
579 /* Name resolution prefs */
580 g_strlcpy(label_str, "Name Resolution", MAX_TREE_NODE_NAME_LEN);
581 prefs_nb_page_add(prefs_nb, label_str, nameres_prefs_show(), E_NAMERES_PAGE_KEY);
582 prefs_tree_page_add(label_str, cts.page, store, NULL);
585 /* TAPS player prefs */
586 g_strlcpy(label_str, "Statistics", MAX_TREE_NODE_NAME_LEN);
587 prefs_nb_page_add(prefs_nb, label_str, stats_prefs_show(), E_TAPS_PAGE_KEY);
588 prefs_tree_page_add(label_str, cts.page, store, NULL);
591 /* Registered prefs */
592 cts.notebook = prefs_nb;
593 cts.is_protocol = FALSE;
594 prefs_modules_foreach_submodules(NULL, module_prefs_show, &cts);
596 /* Button row: OK and alike buttons */
597 bbox = dlg_button_row_new(GTK_STOCK_HELP, GTK_STOCK_OK, GTK_STOCK_APPLY, GTK_STOCK_SAVE, GTK_STOCK_CANCEL, NULL);
598 gtk_box_pack_start(GTK_BOX(cts.main_vb), bbox, FALSE, FALSE, 0);
599 gtk_widget_show(bbox);
601 ok_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_OK);
602 g_signal_connect(ok_bt, "clicked", G_CALLBACK(prefs_main_ok_cb), prefs_w);
604 apply_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_APPLY);
605 g_signal_connect(apply_bt, "clicked", G_CALLBACK(prefs_main_apply_cb), prefs_w);
607 save_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_SAVE);
608 g_signal_connect(save_bt, "clicked", G_CALLBACK(prefs_main_save_cb), prefs_w);
609 g_object_set_data(G_OBJECT(prefs_w), E_PREFSW_SAVE_BT_KEY, save_bt);
611 cancel_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_CANCEL);
612 g_signal_connect(cancel_bt, "clicked", G_CALLBACK(prefs_main_cancel_cb), prefs_w);
613 window_set_cancel_button(prefs_w, cancel_bt, NULL);
615 gtk_widget_grab_default(ok_bt);
617 help_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_HELP);
618 g_signal_connect(help_bt, "clicked", G_CALLBACK(topic_cb), (gpointer)HELP_PREFERENCES_DIALOG);
620 g_signal_connect(prefs_w, "delete_event", G_CALLBACK(prefs_main_delete_event_cb), NULL);
621 g_signal_connect(prefs_w, "destroy", G_CALLBACK(prefs_main_destroy_cb), prefs_w);
623 gtk_widget_show(prefs_w);
625 /* hide the Save button if the user uses implicit save */
626 if(!prefs.gui_use_pref_save) {
627 gtk_widget_hide(save_bt);
630 window_present(prefs_w);
632 switch (prefs_page) {
633 case PREFS_PAGE_LAYOUT:
634 gtk_tree_selection_select_iter(selection, &layout_iter);
635 gtk_notebook_set_current_page(g_object_get_data(G_OBJECT(prefs_w), E_PREFSW_NOTEBOOK_KEY), layout_page);
637 case PREFS_PAGE_COLUMNS:
638 gtk_tree_selection_select_iter(selection, &columns_iter);
639 gtk_notebook_set_current_page(g_object_get_data(G_OBJECT(prefs_w), E_PREFSW_NOTEBOOK_KEY), columns_page);
642 /* Not implemented yet */
646 g_object_unref(G_OBJECT(store));
650 set_option_label(GtkWidget *main_tb, int table_position,
651 const gchar *label_text, const gchar *tooltip_text, GtkTooltips *tooltips)
654 GtkWidget *event_box;
656 label = gtk_label_new(label_text);
657 gtk_misc_set_alignment(GTK_MISC(label), 1.0f, 0.5f);
658 gtk_widget_show(label);
660 event_box = gtk_event_box_new();
661 gtk_event_box_set_visible_window (GTK_EVENT_BOX(event_box), FALSE);
662 gtk_table_attach_defaults(GTK_TABLE(main_tb), event_box, 0, 1,
663 table_position, table_position + 1);
664 if (tooltip_text != NULL && tooltips != NULL)
665 gtk_tooltips_set_tip(tooltips, event_box, tooltip_text, NULL);
666 gtk_container_add(GTK_CONTAINER(event_box), label);
667 gtk_widget_show(event_box);
671 create_preference_check_button(GtkWidget *main_tb, int table_position,
672 const gchar *label_text, const gchar *tooltip_text, gboolean active)
674 GtkTooltips *tooltips;
675 GtkWidget *check_box;
677 tooltips = g_object_get_data(G_OBJECT(main_tb), E_TOOLTIPS_KEY);
679 set_option_label(main_tb, table_position, label_text, tooltip_text,
682 check_box = gtk_check_button_new();
683 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check_box), active);
684 gtk_table_attach_defaults(GTK_TABLE(main_tb), check_box, 1, 2,
685 table_position, table_position + 1);
686 if (tooltip_text != NULL && tooltips != NULL)
687 gtk_tooltips_set_tip(tooltips, check_box, tooltip_text, NULL);
693 create_preference_radio_buttons(GtkWidget *main_tb, int table_position,
694 const gchar *label_text, const gchar *tooltip_text,
695 const enum_val_t *enumvals, gint current_val)
697 GtkTooltips *tooltips;
698 GtkWidget *radio_button_hbox, *button = NULL;
701 const enum_val_t *enum_valp;
702 GtkWidget *event_box;
704 tooltips = g_object_get_data(G_OBJECT(main_tb), E_TOOLTIPS_KEY);
706 set_option_label(main_tb, table_position, label_text, tooltip_text,
709 radio_button_hbox = gtk_hbox_new(FALSE, 0);
711 for (enum_valp = enumvals, idx = 0; enum_valp->name != NULL;
712 enum_valp++, idx++) {
713 button = gtk_radio_button_new_with_label(rb_group,
714 enum_valp->description);
715 gtk_widget_show(button);
716 rb_group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(button));
717 gtk_box_pack_start(GTK_BOX(radio_button_hbox), button, FALSE,
719 if (enum_valp->value == current_val) {
720 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button),
724 gtk_widget_show(radio_button_hbox);
726 event_box = gtk_event_box_new();
727 gtk_event_box_set_visible_window (GTK_EVENT_BOX(event_box), FALSE);
728 gtk_container_add(GTK_CONTAINER(event_box), radio_button_hbox);
729 gtk_table_attach_defaults(GTK_TABLE(main_tb), event_box, 1, 2,
730 table_position, table_position+1);
731 if (tooltip_text != NULL && tooltips != NULL)
732 gtk_tooltips_set_tip(tooltips, event_box, tooltip_text, NULL);
733 gtk_widget_show(event_box);
736 * It doesn't matter which of the buttons we return - we fetch
737 * the value by looking at the entire radio button group to
738 * which it belongs, and we can get that from any button.
744 label_to_enum_val(GtkWidget *label, const enum_val_t *enumvals)
746 const gchar *label_string;
749 /* Get the label's text, and translate it to a value.
750 We match only the descriptions, as those are what appear in
751 the option menu items or as labels for radio buttons.
752 We fail if we don't find a match, as that "can't happen". */
753 label_string = gtk_label_get_text(GTK_LABEL(label));
755 for (i = 0; enumvals[i].name != NULL; i++) {
756 if (g_ascii_strcasecmp(label_string, enumvals[i].description) == 0) {
757 return enumvals[i].value;
760 g_assert_not_reached();
765 fetch_preference_radio_buttons_val(GtkWidget *button,
766 const enum_val_t *enumvals)
772 * Go through the list of of radio buttons in the button's group,
773 * and find the first one that's active.
775 rb_group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(button));
777 for (rb_entry = rb_group; rb_entry != NULL;
778 rb_entry = g_slist_next(rb_entry)) {
779 button = rb_entry->data;
780 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button)))
784 /* OK, now return the value corresponding to that button's label. */
785 return label_to_enum_val(gtk_bin_get_child(GTK_BIN(button)), enumvals);
789 create_preference_option_menu(GtkWidget *main_tb, int table_position,
790 const gchar *label_text, const gchar *tooltip_text,
791 const enum_val_t *enumvals, gint current_val)
793 GtkTooltips *tooltips;
794 GtkWidget *menu_box, *combo_box;
796 const enum_val_t *enum_valp;
797 GtkWidget *event_box;
799 tooltips = g_object_get_data(G_OBJECT(main_tb), E_TOOLTIPS_KEY);
801 set_option_label(main_tb, table_position, label_text, tooltip_text,
804 /* Create a menu from the enumvals */
805 combo_box = gtk_combo_box_new_text ();
806 if (tooltip_text != NULL && tooltips != NULL)
807 gtk_tooltips_set_tip(tooltips, combo_box, tooltip_text, NULL);
809 for (enum_valp = enumvals, idx = 0; enum_valp->name != NULL;
810 enum_valp++, idx++) {
811 gtk_combo_box_append_text (GTK_COMBO_BOX (combo_box), enum_valp->description);
812 if (enum_valp->value == current_val)
815 /* Set the current value active */
816 gtk_combo_box_set_active(GTK_COMBO_BOX(combo_box), menu_idx);
819 * Put the combo box in an hbox, so that it's only as wide
820 * as the widest entry, rather than being as wide as the table
823 menu_box = gtk_hbox_new(FALSE, 0);
824 gtk_box_pack_start(GTK_BOX(menu_box), combo_box, FALSE, FALSE, 0);
826 event_box = gtk_event_box_new();
827 gtk_event_box_set_visible_window (GTK_EVENT_BOX(event_box), FALSE);
828 gtk_table_attach_defaults(GTK_TABLE(main_tb), event_box,
829 1, 2, table_position, table_position + 1);
830 if (tooltip_text != NULL && tooltips != NULL)
831 gtk_tooltips_set_tip(tooltips, event_box, tooltip_text, NULL);
832 gtk_container_add(GTK_CONTAINER(event_box), menu_box);
838 fetch_preference_option_menu_val(GtkWidget *combo_box, const enum_val_t *enumvals)
841 * OK, now return the value corresponding to the label for the
842 * currently active entry in the combo box.
846 i = gtk_combo_box_get_active (GTK_COMBO_BOX(combo_box));
848 return enumvals[i].value;
852 create_preference_entry(GtkWidget *main_tb, int table_position,
853 const gchar *label_text, const gchar *tooltip_text, char *value)
855 GtkTooltips *tooltips;
858 tooltips = g_object_get_data(G_OBJECT(main_tb), E_TOOLTIPS_KEY);
860 set_option_label(main_tb, table_position, label_text, tooltip_text,
863 entry = gtk_entry_new();
865 gtk_entry_set_text(GTK_ENTRY(entry), value);
866 gtk_table_attach_defaults(GTK_TABLE(main_tb), entry, 1, 2,
867 table_position, table_position + 1);
868 if (tooltip_text != NULL && tooltips != NULL)
869 gtk_tooltips_set_tip(tooltips, entry, tooltip_text, NULL);
870 gtk_widget_show(entry);
876 create_preference_static_text(GtkWidget *main_tb, int table_position,
877 const gchar *label_text, const gchar *tooltip_text)
879 GtkTooltips *tooltips;
882 tooltips = g_object_get_data(G_OBJECT(main_tb), E_TOOLTIPS_KEY);
884 if(label_text != NULL)
885 label = gtk_label_new(label_text);
887 label = gtk_label_new("");
888 gtk_table_attach_defaults(GTK_TABLE(main_tb), label, 0, 2,
889 table_position, table_position + 1);
890 if (tooltip_text != NULL && tooltips != NULL)
891 gtk_tooltips_set_tip(tooltips, label, tooltip_text, NULL);
892 gtk_widget_show(label);
898 create_preference_uat(GtkWidget *main_tb, int table_position,
899 const gchar *label_text, const gchar *tooltip_text, void* uat)
901 GtkTooltips *tooltips;
902 GtkWidget *button = NULL;
904 tooltips = g_object_get_data(G_OBJECT(main_tb), E_TOOLTIPS_KEY);
906 set_option_label(main_tb, table_position, label_text, tooltip_text,
909 button = gtk_button_new_from_stock(WIRESHARK_STOCK_EDIT);
911 g_signal_connect(button, "clicked", G_CALLBACK(uat_window_cb), uat);
913 gtk_table_attach_defaults(GTK_TABLE(main_tb), button, 1, 2,
914 table_position, table_position+1);
915 if (tooltip_text != NULL && tooltips != NULL)
916 gtk_tooltips_set_tip(tooltips, button, tooltip_text, NULL);
917 gtk_widget_show(button);
924 pref_check(pref_t *pref, gpointer user_data)
928 pref_t **badpref = user_data;
930 /* Fetch the value of the preference, and check whether it's valid. */
931 switch (pref->type) {
934 str_val = gtk_entry_get_text(GTK_ENTRY(pref->control));
937 /* XXX: The following ugly hack prevents a gcc warning
938 "ignoring return value of 'strtoul', declared with attribute warn_unused_result"
939 which can occur when using certain gcc configurations (see _FORTIFY_SOURCE).
940 A dummy variable is not used because when using gcc 4.6 with -Wextra a
941 "set but not used [-Wunused-but-set-variable]" warning will occur.
942 TBD: will this hack pass muster with other validators such as Coverity, CLang, & etc
945 "... perhaps either using spin buttons for numeric preferences, or otherwise making
946 it impossible to type something that's not a number into the GUI for those preferences,
947 and thus avoiding the need to check whether it's a valid number, would also be a good idea."
950 if(strtoul(str_val, &p, pref->info.base)){}
951 if (p == str_val || *p != '\0' || errno != 0) {
953 return PREFS_SET_SYNTAX_ERR; /* number was bad */
958 /* Value can't be bad. */
962 /* Value can't be bad. */
966 /* Value can't be bad. */
970 str_val = gtk_entry_get_text(GTK_ENTRY(pref->control));
972 if (strlen(str_val) != 0) {
975 if (range_convert_str(&newrange, str_val, pref->info.max_value) != CVT_NO_ERROR) {
977 return PREFS_SET_SYNTAX_ERR; /* range was bad */
983 case PREF_STATIC_TEXT:
985 /* Value can't be bad. */
989 g_assert_not_reached();
996 module_prefs_check(module_t *module, gpointer user_data)
998 /* For all preferences in this module, fetch its value from this
999 module's notebook page and check whether it's valid. */
1000 return prefs_pref_foreach(module, pref_check, user_data);
1004 pref_fetch(pref_t *pref, gpointer user_data)
1006 const char *str_val;
1011 gboolean *pref_changed_p = user_data;
1013 /* Fetch the value of the preference, and set the appropriate variable
1015 switch (pref->type) {
1018 str_val = gtk_entry_get_text(GTK_ENTRY(pref->control));
1019 uval = strtoul(str_val, &p, pref->info.base);
1021 if (p == value || *p != '\0')
1022 return PREFS_SET_SYNTAX_ERR; /* number was bad */
1024 if (*pref->varp.uint != uval) {
1025 *pref_changed_p = TRUE;
1026 *pref->varp.uint = uval;
1031 bval = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(pref->control));
1032 if (*pref->varp.boolp != bval) {
1033 *pref_changed_p = TRUE;
1034 *pref->varp.boolp = bval;
1039 if (pref->info.enum_info.radio_buttons) {
1040 enumval = fetch_preference_radio_buttons_val(pref->control,
1041 pref->info.enum_info.enumvals);
1043 enumval = fetch_preference_option_menu_val(pref->control,
1044 pref->info.enum_info.enumvals);
1047 if (*pref->varp.enump != enumval) {
1048 *pref_changed_p = TRUE;
1049 *pref->varp.enump = enumval;
1054 str_val = gtk_entry_get_text(GTK_ENTRY(pref->control));
1055 if (strcmp(*pref->varp.string, str_val) != 0) {
1056 *pref_changed_p = TRUE;
1057 g_free((void *)*pref->varp.string);
1058 *pref->varp.string = g_strdup(str_val);
1067 str_val = gtk_entry_get_text(GTK_ENTRY(pref->control));
1068 ret = range_convert_str(&newrange, str_val, pref->info.max_value);
1069 if (ret != CVT_NO_ERROR)
1071 return PREFS_SET_SYNTAX_ERR; /* range was bad */
1073 return 0; /* XXX - should fail */
1076 if (!ranges_are_equal(*pref->varp.range, newrange)) {
1077 *pref_changed_p = TRUE;
1078 g_free(*pref->varp.range);
1079 *pref->varp.range = newrange;
1086 case PREF_STATIC_TEXT:
1091 g_assert_not_reached();
1098 module_prefs_fetch(module_t *module, gpointer user_data)
1100 gboolean *must_redissect_p = user_data;
1102 /* For all preferences in this module, fetch its value from this
1103 module's notebook page. Find out whether any of them changed. */
1104 module->prefs_changed = FALSE; /* assume none of them changed */
1105 prefs_pref_foreach(module, pref_fetch, &module->prefs_changed);
1107 /* If any of them changed, indicate that we must redissect and refilter
1108 the current capture (if we have one), as the preference change
1109 could cause packets to be dissected differently. */
1110 if (module->prefs_changed)
1111 *must_redissect_p = TRUE;
1113 return 0; /* keep fetching module preferences */
1118 * This function is used to apply changes and update the Wireless Toolbar
1119 * whenever we apply some changes to the WEP preferences
1122 prefs_airpcap_update(void)
1124 GtkWidget *decryption_cm;
1125 GtkWidget *decryption_en;
1126 gboolean wireshark_decryption_was_enabled = FALSE;
1127 gboolean airpcap_decryption_was_enabled = FALSE;
1128 gboolean wireshark_decryption_is_now_enabled = FALSE;
1130 decryption_cm = GTK_WIDGET(g_object_get_data(G_OBJECT(airpcap_tb),AIRPCAP_TOOLBAR_DECRYPTION_KEY));
1131 decryption_en = GTK_WIDGET(GTK_ENTRY(GTK_COMBO(decryption_cm)->entry));
1133 if( g_ascii_strcasecmp(gtk_entry_get_text(GTK_ENTRY(decryption_en)),AIRPCAP_DECRYPTION_TYPE_STRING_WIRESHARK) == 0 )
1135 wireshark_decryption_was_enabled = TRUE;
1136 airpcap_decryption_was_enabled = FALSE;
1138 else if( g_ascii_strcasecmp(gtk_entry_get_text(GTK_ENTRY(decryption_en)),AIRPCAP_DECRYPTION_TYPE_STRING_AIRPCAP) == 0 )
1140 wireshark_decryption_was_enabled = FALSE;
1141 airpcap_decryption_was_enabled = TRUE;
1143 else if( g_ascii_strcasecmp(gtk_entry_get_text(GTK_ENTRY(decryption_en)),AIRPCAP_DECRYPTION_TYPE_STRING_NONE) == 0 )
1145 wireshark_decryption_was_enabled = FALSE;
1146 airpcap_decryption_was_enabled = FALSE;
1149 wireshark_decryption_is_now_enabled = wireshark_decryption_on();
1151 if(wireshark_decryption_is_now_enabled && airpcap_decryption_was_enabled)
1153 set_airpcap_decryption(FALSE);
1154 gtk_entry_set_text(GTK_ENTRY(decryption_en),AIRPCAP_DECRYPTION_TYPE_STRING_WIRESHARK);
1156 if(wireshark_decryption_is_now_enabled && !airpcap_decryption_was_enabled)
1158 set_airpcap_decryption(FALSE);
1159 gtk_entry_set_text(GTK_ENTRY(decryption_en),AIRPCAP_DECRYPTION_TYPE_STRING_WIRESHARK);
1161 else if(!wireshark_decryption_is_now_enabled && wireshark_decryption_was_enabled)
1163 if(airpcap_decryption_was_enabled)
1165 set_airpcap_decryption(TRUE);
1166 gtk_entry_set_text(GTK_ENTRY(decryption_en),AIRPCAP_DECRYPTION_TYPE_STRING_AIRPCAP);
1170 set_airpcap_decryption(FALSE);
1171 gtk_entry_set_text(GTK_ENTRY(decryption_en),AIRPCAP_DECRYPTION_TYPE_STRING_NONE);
1178 pref_clean(pref_t *pref, gpointer user_data _U_)
1180 switch (pref->type) {
1192 if (pref->saved_val.string != NULL) {
1193 g_free(pref->saved_val.string);
1194 pref->saved_val.string = NULL;
1199 if (pref->saved_val.range != NULL) {
1200 g_free(pref->saved_val.range);
1201 pref->saved_val.range = NULL;
1205 case PREF_STATIC_TEXT:
1210 g_assert_not_reached();
1217 module_prefs_clean(module_t *module, gpointer user_data _U_)
1219 /* For all preferences in this module, clean up any cruft allocated for
1220 use by the GUI code. */
1221 prefs_pref_foreach(module, pref_clean, NULL);
1222 return 0; /* keep cleaning modules */
1225 /* fetch all pref values from all pages */
1227 prefs_main_fetch_all(GtkWidget *dlg, gboolean *must_redissect)
1231 /* First, check that the values are all valid. */
1232 /* XXX - check the non-registered preferences too */
1233 switch (prefs_modules_foreach(module_prefs_check, (gpointer)&badpref)) {
1235 case PREFS_SET_SYNTAX_ERR:
1236 switch (badpref->type) {
1239 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1240 "The value for \"%s\" isn't a valid number.",
1245 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1246 "The value for \"%s\" isn't a valid range.",
1251 g_assert_not_reached();
1256 /* Fetch the preferences (i.e., make sure all the values set in all of
1257 the preferences panes have been copied to "prefs" and the registered
1259 gui_prefs_fetch(g_object_get_data(G_OBJECT(dlg), E_GUI_PAGE_KEY));
1260 layout_prefs_fetch(g_object_get_data(G_OBJECT(dlg), E_GUI_LAYOUT_PAGE_KEY));
1261 column_prefs_fetch(g_object_get_data(G_OBJECT(dlg), E_GUI_COLUMN_PAGE_KEY));
1262 stream_prefs_fetch(g_object_get_data(G_OBJECT(dlg), E_GUI_COLORS_PAGE_KEY));
1266 /* Is WPcap loaded? */
1269 capture_prefs_fetch(g_object_get_data(G_OBJECT(dlg), E_CAPTURE_PAGE_KEY));
1273 #endif /* HAVE_LIBPCAP */
1274 printer_prefs_fetch(g_object_get_data(G_OBJECT(dlg), E_PRINT_PAGE_KEY));
1275 nameres_prefs_fetch(g_object_get_data(G_OBJECT(dlg), E_NAMERES_PAGE_KEY));
1276 stats_prefs_fetch(g_object_get_data(G_OBJECT(dlg), E_TAPS_PAGE_KEY));
1277 protocols_prefs_fetch(g_object_get_data(G_OBJECT(dlg), E_PROTOCOLS_PAGE_KEY));
1278 prefs_modules_foreach(module_prefs_fetch, must_redissect);
1283 /* apply all pref values to the real world */
1285 prefs_main_apply_all(GtkWidget *dlg, gboolean redissect)
1290 * Apply the protocol preferences first - "gui_prefs_apply()" could
1291 * cause redissection, and we have to make sure the protocol
1292 * preference changes have been fully applied.
1296 gui_prefs_apply(g_object_get_data(G_OBJECT(dlg), E_GUI_PAGE_KEY), redissect);
1297 layout_prefs_apply(g_object_get_data(G_OBJECT(dlg), E_GUI_LAYOUT_PAGE_KEY));
1298 column_prefs_apply(g_object_get_data(G_OBJECT(dlg), E_GUI_COLUMN_PAGE_KEY));
1299 stream_prefs_apply(g_object_get_data(G_OBJECT(dlg), E_GUI_COLORS_PAGE_KEY));
1303 /* Is WPcap loaded? */
1306 capture_prefs_apply(g_object_get_data(G_OBJECT(dlg), E_CAPTURE_PAGE_KEY));
1310 #endif /* HAVE_LIBPCAP */
1311 printer_prefs_apply(g_object_get_data(G_OBJECT(dlg), E_PRINT_PAGE_KEY));
1312 nameres_prefs_apply(g_object_get_data(G_OBJECT(dlg), E_NAMERES_PAGE_KEY));
1313 stats_prefs_apply(g_object_get_data(G_OBJECT(dlg), E_TAPS_PAGE_KEY));
1314 protocols_prefs_apply(g_object_get_data(G_OBJECT(dlg), E_PROTOCOLS_PAGE_KEY));
1316 /* show/hide the Save button - depending on setting */
1317 save_bt = g_object_get_data(G_OBJECT(prefs_w), E_PREFSW_SAVE_BT_KEY);
1318 if(prefs.gui_use_pref_save) {
1319 gtk_widget_show(save_bt);
1321 gtk_widget_hide(save_bt);
1326 /* destroy all preferences ressources from all pages */
1328 prefs_main_destroy_all(GtkWidget *dlg)
1334 (frame = gtk_notebook_get_nth_page(g_object_get_data(G_OBJECT(prefs_w), E_PREFSW_NOTEBOOK_KEY), page_num)) != NULL;
1336 if(g_object_get_data(G_OBJECT(frame), E_PAGE_ITER_KEY))
1337 gtk_tree_iter_free(g_object_get_data(G_OBJECT(frame), E_PAGE_ITER_KEY));
1340 gui_prefs_destroy(g_object_get_data(G_OBJECT(dlg), E_GUI_PAGE_KEY));
1341 layout_prefs_destroy(g_object_get_data(G_OBJECT(dlg), E_GUI_LAYOUT_PAGE_KEY));
1342 column_prefs_destroy(g_object_get_data(G_OBJECT(dlg), E_GUI_COLUMN_PAGE_KEY));
1343 stream_prefs_destroy(g_object_get_data(G_OBJECT(dlg), E_GUI_COLORS_PAGE_KEY));
1347 /* Is WPcap loaded? */
1350 capture_prefs_destroy(g_object_get_data(G_OBJECT(dlg), E_CAPTURE_PAGE_KEY));
1354 #endif /* HAVE_LIBPCAP */
1355 printer_prefs_destroy(g_object_get_data(G_OBJECT(dlg), E_PRINT_PAGE_KEY));
1356 nameres_prefs_destroy(g_object_get_data(G_OBJECT(dlg), E_NAMERES_PAGE_KEY));
1357 stats_prefs_destroy(g_object_get_data(G_OBJECT(dlg), E_TAPS_PAGE_KEY));
1359 /* Free up the saved preferences (both for "prefs" and for registered
1361 free_prefs(&saved_prefs);
1362 prefs_modules_foreach(module_prefs_clean, NULL);
1363 protocols_prefs_destroy(g_object_get_data(G_OBJECT(dlg), E_PROTOCOLS_PAGE_KEY));
1368 pref_copy(pref_t *pref, gpointer user_data _U_)
1370 switch (pref->type) {
1373 pref->saved_val.uint = *pref->varp.uint;
1377 pref->saved_val.boolval = *pref->varp.boolp;
1381 pref->saved_val.enumval = *pref->varp.enump;
1385 g_free(pref->saved_val.string);
1386 pref->saved_val.string = g_strdup(*pref->varp.string);
1390 g_free(pref->saved_val.range);
1391 pref->saved_val.range = range_copy(*pref->varp.range);
1394 case PREF_STATIC_TEXT:
1399 g_assert_not_reached();
1406 module_prefs_copy(module_t *module, gpointer user_data _U_)
1408 /* For all preferences in this module, (re)save current value */
1409 prefs_pref_foreach(module, pref_copy, NULL);
1410 return 0; /* continue making copies */
1413 /* Copy prefs to saved values so we can revert to these values */
1414 /* if the user selects Cancel. */
1415 static void prefs_copy(void) {
1416 free_prefs(&saved_prefs);
1417 copy_prefs(&saved_prefs, &prefs);
1418 prefs_modules_foreach(module_prefs_copy, NULL);
1423 prefs_main_write(void)
1429 /* Create the directory that holds personal configuration files, if
1431 if (create_persconffile_dir(&pf_dir_path) == -1) {
1432 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1433 "Can't create directory\n\"%s\"\nfor preferences file: %s.", pf_dir_path,
1435 g_free(pf_dir_path);
1437 /* Write the preferencs out. */
1438 err = write_prefs(&pf_path);
1440 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1441 "Can't open preferences file\n\"%s\": %s.", pf_path,
1449 * Load the Wireshark decryption keys (just set) and save
1450 * the changes to the adapters' registry
1452 airpcap_load_decryption_keys(airpcap_if_list);
1458 prefs_main_ok_cb(GtkWidget *ok_bt _U_, gpointer parent_w)
1460 gboolean must_redissect = FALSE;
1462 if (!prefs_main_fetch_all(parent_w, &must_redissect))
1463 return; /* Errors in some preference setting - already reported */
1465 /* if we don't have a Save button, just save the settings now */
1466 if (!prefs.gui_use_pref_save) {
1470 prefs_main_apply_all(parent_w, must_redissect);
1472 /* Fill in capture options with values from the preferences */
1473 prefs_to_capture_opts();
1476 prefs_airpcap_update();
1479 /* Now destroy the "Preferences" dialog. */
1480 window_destroy(GTK_WIDGET(parent_w));
1482 if (must_redissect) {
1483 /* Redissect all the packets, and re-evaluate the display filter. */
1484 redissect_packets();
1490 prefs_main_apply_cb(GtkWidget *apply_bt _U_, gpointer parent_w)
1492 gboolean must_redissect = FALSE;
1494 if (!prefs_main_fetch_all(parent_w, &must_redissect))
1495 return; /* Errors in some preference setting - already reported */
1497 /* if we don't have a Save button, just save the settings now */
1498 if (!prefs.gui_use_pref_save) {
1500 prefs_copy(); /* save prefs for reverting if Cancel */
1503 prefs_main_apply_all(parent_w, must_redissect);
1505 /* Fill in capture options with values from the preferences */
1506 prefs_to_capture_opts();
1509 prefs_airpcap_update();
1512 if (must_redissect) {
1513 /* Redissect all the packets, and re-evaluate the display filter. */
1514 redissect_packets();
1519 prefs_main_save_cb(GtkWidget *save_bt _U_, gpointer parent_w)
1521 gboolean must_redissect = FALSE;
1523 if (!prefs_main_fetch_all(parent_w, &must_redissect))
1524 return; /* Errors in some preference setting - already reported */
1527 prefs_copy(); /* save prefs for reverting if Cancel */
1529 /* Now apply those preferences.
1530 XXX - should we do this? The user didn't click "OK" or "Apply".
1533 1) by saving the preferences they presumably indicate that they
1536 2) the next time they fire Wireshark up, those preferences will
1539 3) we'd have to buffer "must_redissect" so that if they do
1540 "Apply" after this, we know we have to redissect;
1542 4) we did apply the protocol preferences, at least, in the past. */
1543 prefs_main_apply_all(parent_w, must_redissect);
1545 /* Fill in capture options with values from the preferences */
1546 prefs_to_capture_opts();
1548 if (must_redissect) {
1549 /* Redissect all the packets, and re-evaluate the display filter. */
1550 redissect_packets();
1555 pref_revert(pref_t *pref, gpointer user_data)
1557 gboolean *pref_changed_p = user_data;
1559 /* Revert the preference to its saved value. */
1560 switch (pref->type) {
1563 if (*pref->varp.uint != pref->saved_val.uint) {
1564 *pref_changed_p = TRUE;
1565 *pref->varp.uint = pref->saved_val.uint;
1570 if (*pref->varp.boolp != pref->saved_val.boolval) {
1571 *pref_changed_p = TRUE;
1572 *pref->varp.boolp = pref->saved_val.boolval;
1577 if (*pref->varp.enump != pref->saved_val.enumval) {
1578 *pref_changed_p = TRUE;
1579 *pref->varp.enump = pref->saved_val.enumval;
1584 if (strcmp(*pref->varp.string, pref->saved_val.string) != 0) {
1585 *pref_changed_p = TRUE;
1586 g_free((void *)*pref->varp.string);
1587 *pref->varp.string = g_strdup(pref->saved_val.string);
1592 if (!ranges_are_equal(*pref->varp.range, pref->saved_val.range)) {
1593 *pref_changed_p = TRUE;
1594 g_free(*pref->varp.range);
1595 *pref->varp.range = range_copy(pref->saved_val.range);
1599 case PREF_STATIC_TEXT:
1604 g_assert_not_reached();
1611 module_prefs_revert(module_t *module, gpointer user_data)
1613 gboolean *must_redissect_p = user_data;
1615 /* For all preferences in this module, revert its value to the value
1616 it had when we popped up the Preferences dialog. Find out whether
1617 this changes any of them. */
1618 module->prefs_changed = FALSE; /* assume none of them changed */
1619 prefs_pref_foreach(module, pref_revert, &module->prefs_changed);
1621 /* If any of them changed, indicate that we must redissect and refilter
1622 the current capture (if we have one), as the preference change
1623 could cause packets to be dissected differently. */
1624 if (module->prefs_changed)
1625 *must_redissect_p = TRUE;
1626 return 0; /* keep processing modules */
1629 /* cancel button pressed, revert prefs to saved and exit dialog */
1631 prefs_main_cancel_cb(GtkWidget *cancel_bt _U_, gpointer parent_w)
1633 gboolean must_redissect = FALSE;
1635 /* Free up the current preferences and copy the saved preferences to the
1636 current preferences. */
1638 copy_prefs(&prefs, &saved_prefs);
1639 cfile.cinfo.columns_changed = FALSE; /* [XXX: "columns_changed" should treally be stored in prefs struct ??] */
1641 /* Now revert the registered preferences. */
1642 prefs_modules_foreach(module_prefs_revert, &must_redissect);
1644 /* Now apply the reverted-to preferences. */
1645 prefs_main_apply_all(parent_w, must_redissect);
1647 window_destroy(GTK_WIDGET(parent_w));
1649 if (must_redissect) {
1650 /* Redissect all the packets, and re-evaluate the display filter. */
1651 redissect_packets();
1655 /* Treat this as a cancel, by calling "prefs_main_cancel_cb()" */
1657 prefs_main_delete_event_cb(GtkWidget *prefs_w_lcl, GdkEvent *event _U_,
1658 gpointer user_data _U_)
1660 prefs_main_cancel_cb(NULL, prefs_w_lcl);
1665 /* dialog *is* already destroyed, clean up memory and such */
1667 prefs_main_destroy_cb(GtkWidget *win _U_, gpointer parent_w)
1669 prefs_main_destroy_all(parent_w);
1671 /* Note that we no longer have a "Preferences" dialog box. */
1675 struct properties_data {
1681 module_search_properties(module_t *module, gpointer user_data)
1683 struct properties_data *p = (struct properties_data *)user_data;
1685 /* If this module has the specified title, remember it. */
1686 if (strcmp(module->title, p->title) == 0) {
1688 return 1; /* stops the search */
1691 if(prefs_module_has_submodules(module))
1692 return prefs_modules_foreach_submodules(module, module_search_properties, p);
1698 tree_expand_row(GtkTreeModel *model, GtkTreeView *tree_view, GtkTreeIter *iter)
1703 /* expand the parent first */
1704 if(gtk_tree_model_iter_parent(model, &parent, iter))
1705 tree_expand_row(model, tree_view, &parent);
1707 path = gtk_tree_model_get_path(model, iter);
1708 gtk_tree_view_expand_row(tree_view, path, FALSE);
1709 /*expand_tree(tree_view, &parent, NULL, NULL);*/
1711 gtk_tree_path_free(path);
1714 /* select a node in the tree view */
1715 /* XXX - this is almost 100% copied from byte_view_select() in proto_draw.c,
1716 * find a way to combine both to have a generic function for this */
1718 tree_select_node(GtkWidget *tree, prefs_tree_iter *iter)
1720 GtkTreeIter local_iter = *iter;
1721 GtkTreeView *tree_view = GTK_TREE_VIEW(tree);
1722 GtkTreeModel *model;
1723 GtkTreePath *first_path;
1725 model = gtk_tree_view_get_model(tree_view);
1727 /* Expand our field's row */
1728 first_path = gtk_tree_model_get_path(model, &local_iter);
1730 /* expand from the top down */
1731 tree_expand_row(model, tree_view, &local_iter);
1733 /* select our field's row */
1734 gtk_tree_selection_select_path(gtk_tree_view_get_selection(tree_view),
1737 /* And position the window so the selection is visible.
1738 * Position the selection in the middle of the viewable
1740 gtk_tree_view_scroll_to_cell(tree_view, first_path, NULL, TRUE, 0.5f, 0.0f);
1742 gtk_tree_path_free(first_path);
1746 /* search the corresponding protocol page of the currently selected field */
1748 properties_cb(GtkWidget *w, gpointer dummy)
1750 header_field_info *hfinfo;
1752 struct properties_data p;
1756 module_t *page_module;
1758 if (cfile.finfo_selected == NULL) {
1759 /* There is no field selected */
1763 /* Find the title for the protocol for the selected field. */
1764 hfinfo = cfile.finfo_selected->hfinfo;
1765 if (hfinfo->parent == -1)
1766 title = prefs_get_title_by_name(hfinfo->abbrev);
1768 title = prefs_get_title_by_name(proto_registrar_get_abbrev(hfinfo->parent));
1770 return; /* Couldn't find it. XXX - just crash? "Can't happen"? */
1772 /* Find the module for that protocol by searching for one with that title.
1773 XXX - should we just associate protocols with modules directly? */
1776 prefs_modules_foreach_submodules(protocols_module, module_search_properties,
1778 if (p.module == NULL) {
1779 /* We didn't find it - that protocol probably has no preferences. */
1783 /* Create a preferences window, or pop up an existing one. */
1784 if (prefs_w != NULL) {
1785 reactivate_window(prefs_w);
1790 /* Search all the pages in that window for the one with the specified
1793 (sw = gtk_notebook_get_nth_page(g_object_get_data(G_OBJECT(prefs_w), E_PREFSW_NOTEBOOK_KEY), page_num)) != NULL;
1795 /* Get the frame from the scrollable window */
1796 frame = g_object_get_data(G_OBJECT(sw), E_PAGESW_FRAME_KEY);
1797 /* Get the module for this page (non-protocol prefs don't have one). */
1799 page_module = g_object_get_data(G_OBJECT(frame), E_PAGE_MODULE_KEY);
1800 if (page_module != NULL) {
1801 if (page_module == p.module) {
1803 g_object_get_data(G_OBJECT(prefs_w), E_PREFSW_TREE_KEY),
1804 g_object_get_data(G_OBJECT(frame), E_PAGE_ITER_KEY));
1812 /* Prefs tree selection callback. The node data has been loaded with
1813 the proper notebook page to load. */
1815 prefs_tree_select_cb(GtkTreeSelection *sel, gpointer dummy _U_)
1818 GtkTreeModel *model;
1821 if (gtk_tree_selection_get_selected(sel, &model, &iter))
1823 gtk_tree_model_get(model, &iter, 1, &page, -1);
1825 gtk_notebook_set_current_page(g_object_get_data(G_OBJECT(prefs_w), E_PREFSW_NOTEBOOK_KEY), page);
1836 * indent-tabs-mode: nil
1839 * ex: set shiftwidth=2 tabstop=8 expandtab
1840 * :indentSize=2:tabSize=8:noTabs=true: