2 * Routines for handling preferences
4 * Wireshark - Network traffic analyzer
5 * By Gerald Combs <gerald@wireshark.org>
6 * Copyright 1998 Gerald Combs
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
30 #include <epan/packet.h>
31 #include <epan/prefs.h>
32 #include <epan/prefs-int.h>
33 #include <epan/epan_dissect.h>
35 #include "ui/preference_utils.h"
37 #include "ui/gtk/old-gtk-compat.h"
38 #include "ui/gtk/main.h"
39 #include "ui/gtk/prefs_column.h"
40 #include "ui/gtk/prefs_dlg.h"
41 #include "ui/gtk/prefs_filter_expressions.h"
42 #include "ui/gtk/prefs_font_color.h"
43 #include "ui/gtk/prefs_gui.h"
44 #include "ui/gtk/prefs_layout.h"
45 #include "ui/gtk/prefs_capture.h"
46 #include "ui/gtk/gui_utils.h"
47 #include "ui/gtk/dlg_utils.h"
48 #include "ui/gtk/stock_icons.h"
49 #include "ui/gtk/help_dlg.h"
50 #include "ui/gtk/keys.h"
51 #include "ui/gtk/uat_gui.h"
52 #include "ui/gtk/file_dlg.h"
53 #include "ui/gtk/packet_win.h"
54 #include "simple_dialog.h"
58 #include <caputils/capture-wpcap.h>
61 #include <caputils/airpcap.h>
62 #include <caputils/airpcap_loader.h>
63 #include "airpcap_gui_utils.h"
67 static void prefs_main_ok_cb(GtkWidget *, gpointer);
68 static void prefs_main_apply_cb(GtkWidget *, gpointer);
69 static void prefs_main_save_cb(GtkWidget *, gpointer);
70 static void prefs_main_cancel_cb(GtkWidget *, gpointer);
71 static gboolean prefs_main_delete_event_cb(GtkWidget *, GdkEvent *, gpointer);
72 static void prefs_main_destroy_cb(GtkWidget *, gpointer);
73 static void prefs_tree_select_cb(GtkTreeSelection *, gpointer);
75 static GtkWidget *create_preference_path_entry(GtkWidget *, int,
76 const gchar *, const gchar *, char *, gboolean);
78 #define E_PREFSW_SCROLLW_KEY "prefsw_scrollw"
79 #define E_PREFSW_TREE_KEY "prefsw_tree"
80 #define E_PREFSW_NOTEBOOK_KEY "prefsw_notebook"
81 #define E_PREFSW_SAVE_BT_KEY "prefsw_save_bt"
82 #define E_PAGE_ITER_KEY "page_iter"
83 #define E_PAGE_MODULE_KEY "page_module"
84 #define E_PAGESW_FRAME_KEY "pagesw_frame"
86 #define E_GUI_PAGE_KEY "gui_options_page"
87 #define E_GUI_LAYOUT_PAGE_KEY "gui_layout_page"
88 #define E_GUI_COLUMN_PAGE_KEY "gui_column_options_page"
89 #define E_GUI_FONT_PAGE_KEY "gui_font_options_page"
90 #define E_GUI_FONT_COLORS_PAGE_KEY "gui_font_colors_options_page"
91 #define E_CAPTURE_PAGE_KEY "capture_options_page"
92 #define E_NAMERES_PAGE_KEY "nameres_options_page"
93 #define E_FILTER_EXPRESSIONS_PAGE_KEY "filter_expressions_page"
94 #define E_GRID_MODULE_KEY "grid_module"
97 * Keep a static pointer to the current "Preferences" window, if any, so that
98 * if somebody tries to do "Edit:Preferences" while there's already a
99 * "Preferences" window up, we just pop up the existing one, rather than
100 * creating a new one.
102 static GtkWidget *prefs_w;
114 pref_exists(pref_t *pref _U_, gpointer user_data _U_)
119 /* show a single preference on the GtkGrid of a preference page */
121 pref_show(pref_t *pref, gpointer user_data)
123 GtkWidget *main_grid = (GtkWidget *)user_data;
124 module_t *module = (module_t *)g_object_get_data(G_OBJECT(main_grid), E_GRID_MODULE_KEY);
126 const char *type_name = prefs_pref_type_name(pref);
132 /* Give this preference a label which is its title, followed by a colon,
133 and left-align it. */
135 label_len = strlen(title) + 2;
136 label_string = (char *)g_malloc(label_len);
137 g_strlcpy(label_string, title, label_len);
139 tooltip_txt = pref->description? g_strdup_printf("%s\n\nName: %s.%s\nType: %s",
143 type_name ? type_name : "Unknown"
147 * Sometimes we don't want to append a ':' after a static text string...
148 * If it is needed, we will specify it in the string itself.
150 if (pref->type != PREF_STATIC_TEXT)
151 g_strlcat(label_string, ":", label_len);
153 pref_stash(pref, NULL);
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 /* XXX - there are no uint spinbuttons, so we can't use a spinbutton.
162 Even more annoyingly, even if there were, GLib doesn't define
163 G_MAXUINT - but I think ANSI C may define UINT_MAX, so we could
165 switch (pref->info.base) {
168 g_snprintf(uint_str, sizeof(uint_str), "%u", pref->stashed_val.uint);
172 g_snprintf(uint_str, sizeof(uint_str), "%o", pref->stashed_val.uint);
176 g_snprintf(uint_str, sizeof(uint_str), "%x", pref->stashed_val.uint);
179 pref->control = create_preference_entry(main_grid, pref->ordinal,
180 label_string, tooltip_txt,
185 pref->control = create_preference_check_button(main_grid, pref->ordinal,
186 label_string, tooltip_txt,
187 pref->stashed_val.boolval);
191 if (pref->info.enum_info.radio_buttons) {
192 /* Show it as radio buttons. */
193 pref->control = create_preference_radio_buttons(main_grid, pref->ordinal,
194 label_string, tooltip_txt,
195 pref->info.enum_info.enumvals,
196 pref->stashed_val.enumval);
198 /* Show it as an option menu. */
199 pref->control = create_preference_option_menu(main_grid, pref->ordinal,
200 label_string, tooltip_txt,
201 pref->info.enum_info.enumvals,
202 pref->stashed_val.enumval);
207 pref->control = create_preference_entry(main_grid, pref->ordinal,
208 label_string, tooltip_txt,
209 pref->stashed_val.string);
213 pref->control = create_preference_path_entry(main_grid, pref->ordinal,
216 pref->stashed_val.string, FALSE);
220 pref->control = create_preference_path_entry(main_grid, pref->ordinal,
223 pref->stashed_val.string, TRUE);
230 range_str_p = range_convert_range(*pref->varp.range);
231 pref->control = create_preference_entry(main_grid, pref->ordinal,
232 label_string, tooltip_txt,
237 case PREF_STATIC_TEXT:
239 pref->control = create_preference_static_text(main_grid, pref->ordinal,
240 label_string, tooltip_txt);
246 if (pref->gui == GUI_ALL || pref->gui == GUI_GTK)
247 pref->control = create_preference_uat(main_grid, pref->ordinal,
248 label_string, tooltip_txt,
255 /* currently not supported */
258 g_assert_not_reached();
262 g_free(label_string);
267 #define prefs_tree_iter GtkTreeIter
269 /* add a page to the tree */
270 static prefs_tree_iter
271 prefs_tree_page_add(const gchar *title, gint page_nr,
272 gpointer store, prefs_tree_iter *parent_iter)
274 prefs_tree_iter iter;
276 gtk_tree_store_append((GtkTreeStore *)store, &iter, parent_iter);
277 gtk_tree_store_set((GtkTreeStore *)store, &iter, 0, title, 1, page_nr, -1);
281 /* add a page to the notebook */
283 prefs_nb_page_add(GtkWidget *notebook, const gchar *title _U_, GtkWidget *page, const char *page_key)
288 sw = gtk_scrolled_window_new(NULL, NULL);
289 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
292 frame = gtk_frame_new(NULL);
293 gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_NONE);
294 gtk_container_set_border_width(GTK_CONTAINER(frame), DLG_OUTER_MARGIN);
295 #if ! GTK_CHECK_VERSION(3,8,0)
296 gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(sw), frame);
298 gtk_container_add(GTK_CONTAINER(sw), frame);
300 gtk_widget_show(frame);
303 gtk_container_add(GTK_CONTAINER(frame), page);
304 g_object_set_data(G_OBJECT(prefs_w), page_key, page);
307 gtk_notebook_append_page (GTK_NOTEBOOK(notebook), sw, NULL);
312 #define MAX_TREE_NODE_NAME_LEN 64
314 /* show prefs page for each registered module (protocol) */
316 module_prefs_show(module_t *module, gpointer user_data)
318 struct ct_struct *cts = (struct ct_struct *)user_data;
319 struct ct_struct child_cts;
320 GtkWidget *main_vb, *main_grid, *frame, *main_sw;
321 gchar label_str[MAX_TREE_NODE_NAME_LEN];
325 if (!module->use_gui) {
326 /* This module uses its own GUI interface to modify its
327 * preferences, so ignore it
333 * Is this module an interior node, with modules underneath it?
335 if (!prefs_module_has_submodules(module)) {
338 * Does it have any preferences (other than possibly obsolete ones)?
340 if (prefs_pref_foreach(module, pref_exists, NULL) == 0) {
342 * No. Don't put the module into the preferences window,
343 * as there's nothing to show.
345 * XXX - we should do the same for interior ndes; if the module
346 * has no non-obsolete preferences *and* nothing under it has
347 * non-obsolete preferences, don't put it into the window.
354 * Add this module to the tree.
356 g_strlcpy(label_str, module->title, MAX_TREE_NODE_NAME_LEN);
357 model = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(cts->tree)));
359 if (module->parent == NULL)
360 gtk_tree_store_append(model, &iter, NULL);
362 gtk_tree_store_append(model, &iter, &cts->iter);
365 * Is this an interior node?
367 if (prefs_module_has_submodules(module)) {
371 gtk_tree_store_set(model, &iter, 0, label_str, 1, -1, -1);
374 * Walk the subtree and attach stuff to it.
377 child_cts.iter = iter;
378 prefs_modules_foreach_submodules(module, module_prefs_show, &child_cts);
380 /* keep the page count right */
381 cts->page = child_cts.page;
385 * We create pages for interior nodes even if they don't have
386 * preferences, so that we at least have something to show
387 * if the user clicks on them, even if it's empty.
390 /* Scrolled window */
391 main_sw = gtk_scrolled_window_new(NULL, NULL);
392 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(main_sw), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
395 frame = gtk_frame_new(NULL);
396 gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_NONE);
397 gtk_container_set_border_width(GTK_CONTAINER(frame), DLG_OUTER_MARGIN);
398 #if ! GTK_CHECK_VERSION(3,8,0)
399 gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(main_sw), frame);
401 gtk_container_add(GTK_CONTAINER(main_sw), frame);
403 g_object_set_data(G_OBJECT(main_sw), E_PAGESW_FRAME_KEY, frame);
405 /* Main vertical box */
406 main_vb = ws_gtk_box_new(GTK_ORIENTATION_VERTICAL, 5, FALSE);
407 gtk_container_set_border_width(GTK_CONTAINER(main_vb), 5);
408 gtk_container_add(GTK_CONTAINER(frame), main_vb);
411 main_grid = ws_gtk_grid_new();
412 gtk_box_pack_start(GTK_BOX(main_vb), main_grid, FALSE, FALSE, 0);
413 #if GTK_CHECK_VERSION(3,0,0)
414 gtk_widget_set_vexpand(GTK_WIDGET(main_grid), FALSE); /* Ignore VEXPAND requests from children */
416 ws_gtk_grid_set_row_spacing(GTK_GRID(main_grid), 10);
417 ws_gtk_grid_set_column_spacing(GTK_GRID(main_grid), 15);
419 /* Add items for each of the preferences */
420 g_object_set_data(G_OBJECT(main_grid), E_GRID_MODULE_KEY, module);
421 prefs_pref_foreach(module, pref_show, main_grid);
422 g_object_set_data(G_OBJECT(main_grid), E_GRID_MODULE_KEY, NULL);
424 /* Associate this module with the page's frame. */
425 g_object_set_data(G_OBJECT(frame), E_PAGE_MODULE_KEY, module);
427 /* Add the page to the notebook */
428 gtk_notebook_append_page(GTK_NOTEBOOK(cts->notebook), main_sw, NULL);
430 /* Attach the page to the tree item */
431 gtk_tree_store_set(model, &iter, 0, label_str, 1, cts->page, -1);
432 g_object_set_data(G_OBJECT(frame), E_PAGE_ITER_KEY, gtk_tree_iter_copy(&iter));
436 /* Show 'em what we got */
437 gtk_widget_show_all(main_sw);
443 /* show the dialog */
445 prefs_cb(GtkWidget *w, gpointer dummy)
447 prefs_page_cb (w, dummy, PREFS_PAGE_USER_INTERFACE);
451 prefs_page_cb(GtkWidget *w _U_, gpointer dummy _U_, PREFS_PAGE_E prefs_page)
453 GtkWidget *top_hb, *bbox, *prefs_nb, *ct_sb,
454 *ok_bt, *apply_bt, *save_bt, *cancel_bt, *help_bt;
455 gchar label_str[MAX_TREE_NODE_NAME_LEN];
456 struct ct_struct cts;
458 GtkTreeSelection *selection;
459 GtkCellRenderer *renderer;
460 GtkTreeViewColumn *column;
462 prefs_tree_iter gui_iter, layout_iter, columns_iter, capture_iter;
463 gint layout_page, columns_page;
464 gint capture_page = 0;
467 if (prefs_w != NULL) {
468 /* There's already a "Preferences" dialog box; reactivate it. */
469 reactivate_window(prefs_w);
473 prefs_w = dlg_conf_window_new("Wireshark: Preferences");
474 gtk_window_set_default_size(GTK_WINDOW(prefs_w), 400, 650);
477 * Unfortunately, we can't arrange that a GtkGrid widget wrap an event box
478 * around a grid row, so the spacing between the preference item's label
479 * and its control widgets is inactive and the tooltip doesn't pop up when
480 * the mouse is over it.
483 /* Container for each row of widgets */
484 cts.main_vb = ws_gtk_box_new(GTK_ORIENTATION_VERTICAL, 5, FALSE);
485 gtk_container_set_border_width(GTK_CONTAINER(cts.main_vb), 5);
486 gtk_container_add(GTK_CONTAINER(prefs_w), cts.main_vb);
487 gtk_widget_show(cts.main_vb);
489 /* Top row: Preferences tree and notebook */
490 top_hb = ws_gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 10, FALSE);
491 gtk_box_pack_start(GTK_BOX(cts.main_vb), top_hb, TRUE, TRUE, 0);
492 gtk_widget_show(top_hb);
494 /* scrolled window on the left for the categories tree */
495 ct_sb = scrolled_window_new(NULL, NULL);
496 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(ct_sb),
498 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(ct_sb),
499 GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
500 gtk_box_pack_start(GTK_BOX(top_hb), ct_sb, TRUE, TRUE, 0);
501 gtk_widget_show(ct_sb);
502 g_object_set_data(G_OBJECT(prefs_w), E_PREFSW_SCROLLW_KEY, ct_sb);
504 /* categories tree */
505 store = gtk_tree_store_new(2, G_TYPE_STRING, G_TYPE_INT);
506 cts.tree = tree_view_new(GTK_TREE_MODEL(store));
507 cts.iter.stamp = 0; /* mark this as the toplevel */
508 g_object_set_data(G_OBJECT(prefs_w), E_PREFSW_TREE_KEY, cts.tree);
509 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(cts.tree), FALSE);
510 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(cts.tree));
511 gtk_tree_selection_set_mode(selection, GTK_SELECTION_SINGLE);
512 renderer = gtk_cell_renderer_text_new();
513 col_offset = gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(cts.tree),
514 -1, "Name", renderer,
516 column = gtk_tree_view_get_column(GTK_TREE_VIEW(cts.tree),
518 gtk_tree_view_column_set_sizing(GTK_TREE_VIEW_COLUMN(column),
519 GTK_TREE_VIEW_COLUMN_AUTOSIZE);
520 g_signal_connect(selection, "changed", G_CALLBACK(prefs_tree_select_cb), NULL);
521 gtk_container_add(GTK_CONTAINER(ct_sb), cts.tree);
522 gtk_widget_show(cts.tree);
524 /* A notebook widget without tabs is used to flip between prefs */
525 prefs_nb = gtk_notebook_new();
526 g_object_set_data(G_OBJECT(prefs_w), E_PREFSW_NOTEBOOK_KEY, prefs_nb);
527 gtk_notebook_set_show_tabs(GTK_NOTEBOOK(prefs_nb), FALSE);
528 gtk_notebook_set_show_border(GTK_NOTEBOOK(prefs_nb), FALSE);
529 gtk_box_pack_start(GTK_BOX(top_hb), prefs_nb, TRUE, TRUE, 0);
530 gtk_widget_show(prefs_nb);
535 g_strlcpy(label_str, "User Interface", MAX_TREE_NODE_NAME_LEN);
536 prefs_nb_page_add(prefs_nb, label_str, gui_prefs_show(), E_GUI_PAGE_KEY);
537 gui_iter = prefs_tree_page_add(label_str, cts.page, store, NULL);
540 /* GUI layout prefs */
541 g_strlcpy(label_str, "Layout", MAX_TREE_NODE_NAME_LEN);
542 prefs_nb_page_add(prefs_nb, label_str, layout_prefs_show(), E_GUI_LAYOUT_PAGE_KEY);
543 layout_iter = prefs_tree_page_add(label_str, cts.page, store, &gui_iter);
544 layout_page = cts.page++;
546 /* GUI Column prefs */
547 g_strlcpy(label_str, "Columns", MAX_TREE_NODE_NAME_LEN);
548 prefs_nb_page_add(prefs_nb, label_str, column_prefs_show(prefs_w), E_GUI_COLUMN_PAGE_KEY);
549 columns_iter = prefs_tree_page_add(label_str, cts.page, store, &gui_iter);
550 columns_page = cts.page++;
552 /* GUI Colors prefs */
553 g_strlcpy(label_str, "Font and Colors", MAX_TREE_NODE_NAME_LEN);
554 prefs_nb_page_add(prefs_nb, label_str, font_color_prefs_show(), E_GUI_FONT_COLORS_PAGE_KEY);
555 prefs_tree_page_add(label_str, cts.page, store, &gui_iter);
558 /* select the main GUI page as the default page and expand its children */
559 gtk_tree_selection_select_iter(selection, &gui_iter);
560 /* (expand will only take effect, when at least one child exists) */
561 gtk_tree_view_expand_all(GTK_TREE_VIEW(cts.tree));
565 /* Is WPcap loaded? */
569 g_strlcpy(label_str, "Capture", MAX_TREE_NODE_NAME_LEN);
570 prefs_nb_page_add(prefs_nb, label_str, capture_prefs_show(), E_CAPTURE_PAGE_KEY);
571 capture_iter = prefs_tree_page_add(label_str, cts.page, store, NULL);
572 capture_page = cts.page++;
576 #endif /* HAVE_LIBPCAP */
578 /* Saved filter prefs */
579 g_strlcpy(label_str, "Filter Expressions", MAX_TREE_NODE_NAME_LEN);
580 prefs_nb_page_add(prefs_nb, label_str, filter_expressions_prefs_show(),
581 E_FILTER_EXPRESSIONS_PAGE_KEY);
582 prefs_tree_page_add(label_str, cts.page, store, NULL);
585 /* Registered prefs */
586 cts.notebook = prefs_nb;
588 prefs_modules_foreach_submodules(NULL, module_prefs_show, &cts);
590 /* Button row: OK and alike buttons */
591 bbox = dlg_button_row_new(GTK_STOCK_HELP, GTK_STOCK_OK, GTK_STOCK_APPLY, GTK_STOCK_SAVE, GTK_STOCK_CANCEL, NULL);
592 gtk_box_pack_start(GTK_BOX(cts.main_vb), bbox, FALSE, FALSE, 0);
593 gtk_widget_show(bbox);
595 ok_bt = (GtkWidget *)g_object_get_data(G_OBJECT(bbox), GTK_STOCK_OK);
596 g_signal_connect(ok_bt, "clicked", G_CALLBACK(prefs_main_ok_cb), prefs_w);
598 apply_bt = (GtkWidget *)g_object_get_data(G_OBJECT(bbox), GTK_STOCK_APPLY);
599 g_signal_connect(apply_bt, "clicked", G_CALLBACK(prefs_main_apply_cb), prefs_w);
601 save_bt = (GtkWidget *)g_object_get_data(G_OBJECT(bbox), GTK_STOCK_SAVE);
602 g_signal_connect(save_bt, "clicked", G_CALLBACK(prefs_main_save_cb), prefs_w);
603 g_object_set_data(G_OBJECT(prefs_w), E_PREFSW_SAVE_BT_KEY, save_bt);
605 cancel_bt = (GtkWidget *)g_object_get_data(G_OBJECT(bbox), GTK_STOCK_CANCEL);
606 g_signal_connect(cancel_bt, "clicked", G_CALLBACK(prefs_main_cancel_cb), prefs_w);
607 window_set_cancel_button(prefs_w, cancel_bt, NULL);
609 gtk_widget_grab_default(ok_bt);
611 help_bt = (GtkWidget *)g_object_get_data(G_OBJECT(bbox), GTK_STOCK_HELP);
612 g_signal_connect(help_bt, "clicked", G_CALLBACK(topic_cb), (gpointer)HELP_PREFERENCES_DIALOG);
614 g_signal_connect(prefs_w, "delete_event", G_CALLBACK(prefs_main_delete_event_cb), NULL);
615 g_signal_connect(prefs_w, "destroy", G_CALLBACK(prefs_main_destroy_cb), prefs_w);
617 gtk_widget_show(prefs_w);
619 /* hide the Save button if the user uses implicit save */
620 if (!prefs.gui_use_pref_save) {
621 gtk_widget_hide(save_bt);
624 window_present(prefs_w);
626 switch (prefs_page) {
627 case PREFS_PAGE_LAYOUT:
628 gtk_tree_selection_select_iter(selection, &layout_iter);
629 gtk_notebook_set_current_page((GtkNotebook *)g_object_get_data(G_OBJECT(prefs_w), E_PREFSW_NOTEBOOK_KEY), layout_page);
631 case PREFS_PAGE_COLUMNS:
632 gtk_tree_selection_select_iter(selection, &columns_iter);
633 gtk_notebook_set_current_page((GtkNotebook *)g_object_get_data(G_OBJECT(prefs_w), E_PREFSW_NOTEBOOK_KEY), columns_page);
635 case PREFS_PAGE_CAPTURE:
637 gtk_tree_selection_select_iter(selection, &capture_iter);
638 gtk_notebook_set_current_page((GtkNotebook *)g_object_get_data(G_OBJECT(prefs_w), E_PREFSW_NOTEBOOK_KEY), capture_page);
642 /* Not implemented yet */
646 g_object_unref(G_OBJECT(store));
650 set_option_label(GtkWidget *main_grid, int grid_position,
651 const gchar *label_text, const gchar *tooltip_text)
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 ws_gtk_grid_attach_defaults(GTK_GRID(main_grid), event_box, 0, grid_position, 1, 1);
663 if (tooltip_text != NULL)
664 gtk_widget_set_tooltip_text(event_box, tooltip_text);
665 gtk_container_add(GTK_CONTAINER(event_box), label);
666 gtk_widget_show(event_box);
670 create_preference_check_button(GtkWidget *main_grid, int grid_position,
671 const gchar *label_text, const gchar *tooltip_text, gboolean active)
673 GtkWidget *check_box;
675 set_option_label(main_grid, grid_position, label_text, tooltip_text);
677 check_box = gtk_check_button_new();
678 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check_box), active);
679 ws_gtk_grid_attach_defaults(GTK_GRID(main_grid), check_box, 1, grid_position, 1, 1);
680 if (tooltip_text != NULL)
681 gtk_widget_set_tooltip_text(check_box, tooltip_text);
687 create_preference_radio_buttons(GtkWidget *main_grid, int grid_position,
688 const gchar *label_text, const gchar *tooltip_text,
689 const enum_val_t *enumvals, gint current_val)
691 GtkWidget *radio_button_hbox, *button = NULL;
694 const enum_val_t *enum_valp;
695 GtkWidget *event_box;
697 set_option_label(main_grid, grid_position, label_text, tooltip_text);
699 radio_button_hbox = ws_gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0, FALSE);
701 for (enum_valp = enumvals, idx = 0; enum_valp->name != NULL;
702 enum_valp++, idx++) {
703 button = gtk_radio_button_new_with_label(rb_group,
704 enum_valp->description);
705 gtk_widget_show(button);
706 rb_group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(button));
707 gtk_box_pack_start(GTK_BOX(radio_button_hbox), button, FALSE,
709 if (enum_valp->value == current_val) {
710 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button),
714 gtk_widget_show(radio_button_hbox);
716 event_box = gtk_event_box_new();
717 gtk_event_box_set_visible_window (GTK_EVENT_BOX(event_box), FALSE);
718 gtk_container_add(GTK_CONTAINER(event_box), radio_button_hbox);
719 ws_gtk_grid_attach_defaults(GTK_GRID(main_grid), event_box, 1, grid_position, 1, 1);
720 if (tooltip_text != NULL)
721 gtk_widget_set_tooltip_text(event_box, tooltip_text);
722 gtk_widget_show(event_box);
725 * It doesn't matter which of the buttons we return - we fetch
726 * the value by looking at the entire radio button group to
727 * which it belongs, and we can get that from any button.
733 label_to_enum_val(GtkWidget *label, const enum_val_t *enumvals)
735 const gchar *label_string;
738 /* Get the label's text, and translate it to a value.
739 We match only the descriptions, as those are what appear in
740 the option menu items or as labels for radio buttons.
741 We fail if we don't find a match, as that "can't happen". */
742 label_string = gtk_label_get_text(GTK_LABEL(label));
744 for (i = 0; enumvals[i].name != NULL; i++) {
745 if (g_ascii_strcasecmp(label_string, enumvals[i].description) == 0) {
746 return enumvals[i].value;
749 g_assert_not_reached();
754 fetch_preference_radio_buttons_val(GtkWidget *button,
755 const enum_val_t *enumvals)
761 * Go through the list of of radio buttons in the button's group,
762 * and find the first one that's active.
764 rb_group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(button));
766 for (rb_entry = rb_group; rb_entry != NULL;
767 rb_entry = g_slist_next(rb_entry)) {
768 button = (GtkWidget *)rb_entry->data;
769 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button)))
773 /* OK, now return the value corresponding to that button's label. */
774 return label_to_enum_val(gtk_bin_get_child(GTK_BIN(button)), enumvals);
778 create_preference_option_menu(GtkWidget *main_grid, int grid_position,
779 const gchar *label_text, const gchar *tooltip_text,
780 const enum_val_t *enumvals, gint current_val)
782 GtkWidget *menu_box, *combo_box;
784 const enum_val_t *enum_valp;
785 GtkWidget *event_box;
787 set_option_label(main_grid, grid_position, label_text, tooltip_text);
789 /* Create a menu from the enumvals */
790 combo_box = gtk_combo_box_text_new();
791 if (tooltip_text != NULL)
792 gtk_widget_set_tooltip_text(combo_box, tooltip_text);
794 for (enum_valp = enumvals, idx = 0; enum_valp->name != NULL;
795 enum_valp++, idx++) {
796 gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo_box), enum_valp->description);
797 if (enum_valp->value == current_val)
800 /* Set the current value active */
801 gtk_combo_box_set_active(GTK_COMBO_BOX(combo_box), menu_idx);
804 * Put the combo box in an hbox, so that it's only as wide
805 * as the widest entry, rather than being as wide as the grid
808 menu_box = ws_gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0, FALSE);
809 gtk_box_pack_start(GTK_BOX(menu_box), combo_box, FALSE, FALSE, 0);
811 event_box = gtk_event_box_new();
812 gtk_event_box_set_visible_window (GTK_EVENT_BOX(event_box), FALSE);
813 ws_gtk_grid_attach_defaults(GTK_GRID(main_grid), event_box, 1, grid_position, 1, 1);
814 if (tooltip_text != NULL)
815 gtk_widget_set_tooltip_text(event_box, tooltip_text);
816 gtk_container_add(GTK_CONTAINER(event_box), menu_box);
822 fetch_preference_option_menu_val(GtkWidget *combo_box, const enum_val_t *enumvals)
825 * OK, now return the value corresponding to the label for the
826 * currently active entry in the combo box.
830 i = gtk_combo_box_get_active (GTK_COMBO_BOX(combo_box));
832 return enumvals[i].value;
836 create_preference_entry(GtkWidget *main_grid, int grid_position,
837 const gchar *label_text, const gchar *tooltip_text, char *value)
841 set_option_label(main_grid, grid_position, label_text, tooltip_text);
843 entry = gtk_entry_new();
845 gtk_entry_set_text(GTK_ENTRY(entry), value);
846 ws_gtk_grid_attach_defaults(GTK_GRID(main_grid), entry, 1, grid_position, 1, 1);
847 if (tooltip_text != NULL)
848 gtk_widget_set_tooltip_text(entry, tooltip_text);
849 gtk_widget_show(entry);
855 preference_filename_entry_cb(GtkWidget *button, GtkWidget *filename_te)
857 /* XXX - use a better browser dialog title */
858 file_selection_browse(button, filename_te, "Wireshark: File preference",
859 FILE_SELECTION_READ_BROWSE);
863 preference_dirname_entry_cb(GtkWidget *button, GtkWidget *filename_te)
865 /* XXX - use a better browser dialog title */
866 file_selection_browse(button, filename_te, "Wireshark: Directory preference",
867 FILE_SELECTION_CREATE_FOLDER);
871 create_preference_path_entry(GtkWidget *main_grid, int grid_position,
872 const gchar *label_text, const gchar *tooltip_text, char *value, gboolean dir_only)
875 GtkWidget *button, *file_bt_hb;
877 set_option_label(main_grid, grid_position, label_text, tooltip_text);
878 file_bt_hb = ws_gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0, FALSE);
879 ws_gtk_grid_attach_defaults(GTK_GRID(main_grid), file_bt_hb, 1, grid_position, 1, 1);
880 gtk_widget_show(file_bt_hb);
882 button = ws_gtk_button_new_from_stock(WIRESHARK_STOCK_BROWSE);
883 gtk_box_pack_end(GTK_BOX(file_bt_hb), button, FALSE, FALSE, 0);
884 gtk_widget_show(button);
886 entry = gtk_entry_new();
887 gtk_box_pack_start(GTK_BOX(file_bt_hb), entry, TRUE, TRUE, 0);
889 gtk_entry_set_text(GTK_ENTRY(entry), value);
890 if (tooltip_text != NULL)
891 gtk_widget_set_tooltip_text(entry, tooltip_text);
892 gtk_widget_show(entry);
895 g_signal_connect(button, "clicked", G_CALLBACK(preference_dirname_entry_cb), entry);
897 g_signal_connect(button, "clicked", G_CALLBACK(preference_filename_entry_cb), entry);
904 create_preference_static_text(GtkWidget *main_grid, int grid_position,
905 const gchar *label_text, const gchar *tooltip_text)
909 if (label_text != NULL)
910 label = gtk_label_new(label_text);
912 label = gtk_label_new("");
913 ws_gtk_grid_attach_defaults(GTK_GRID(main_grid), label, 0, grid_position, 2, 1);
914 if (tooltip_text != NULL)
915 gtk_widget_set_tooltip_text(label, tooltip_text);
916 gtk_widget_show(label);
922 create_preference_uat(GtkWidget *main_grid, int grid_position,
923 const gchar *label_text, const gchar *tooltip_text, void* uat)
927 set_option_label(main_grid, grid_position, label_text, tooltip_text);
929 button = ws_gtk_button_new_from_stock(WIRESHARK_STOCK_EDIT);
931 g_signal_connect(button, "clicked", G_CALLBACK(uat_window_cb), uat);
933 ws_gtk_grid_attach_defaults(GTK_GRID(main_grid), button, 1, grid_position, 1, 1);
934 if (tooltip_text != NULL)
935 gtk_widget_set_tooltip_text(button, tooltip_text);
936 gtk_widget_show(button);
943 pref_check(pref_t *pref, gpointer user_data)
947 pref_t **badpref = (pref_t **)user_data;
949 /* Fetch the value of the preference, and check whether it's valid. */
950 switch (pref->type) {
953 str_val = gtk_entry_get_text(GTK_ENTRY(pref->control));
956 /* XXX: The following ugly hack prevents a gcc warning
957 "ignoring return value of 'strtoul', declared with attribute warn_unused_result"
958 which can occur when using certain gcc configurations (see -D_FORTIFY_SOURCE).
959 A dummy variable is not used because when using gcc 4.6 with -Wextra a
960 "set but not used [-Wunused-but-set-variable]" warning will occur.
961 (Coverity & CLang apparently do not object to this hack).
964 "... perhaps either using spin buttons for numeric preferences, or otherwise making
965 it impossible to type something that's not a number into the GUI for those preferences,
966 and thus avoiding the need to check whether it's a valid number, would also be a good idea."
969 if (strtoul(str_val, &p, pref->info.base)){}
970 if (p == str_val || *p != '\0' || errno != 0) {
972 return PREFS_SET_SYNTAX_ERR; /* number was bad */
977 /* Value can't be bad. */
981 /* Value can't be bad. */
987 /* Value can't be bad. */
991 str_val = gtk_entry_get_text(GTK_ENTRY(pref->control));
993 if (strlen(str_val) != 0) {
996 if (range_convert_str(&newrange, str_val, pref->info.max_value) != CVT_NO_ERROR) {
998 return PREFS_SET_SYNTAX_ERR; /* range was bad */
1004 case PREF_STATIC_TEXT:
1006 /* Value can't be bad. */
1011 /* currently not supported */
1014 g_assert_not_reached();
1021 module_prefs_check(module_t *module, gpointer user_data)
1023 /* Ignore any preferences with their own interface */
1024 if (!module->use_gui) {
1028 /* For all preferences in this module, fetch its value from this
1029 module's notebook page and check whether it's valid. */
1030 return prefs_pref_foreach(module, pref_check, user_data);
1034 pref_fetch(pref_t *pref, gpointer user_data)
1036 const char *str_val;
1041 gboolean *pref_changed_p = (gboolean *)user_data;
1043 /* Fetch the value of the preference, and set the appropriate variable
1045 switch (pref->type) {
1048 str_val = gtk_entry_get_text(GTK_ENTRY(pref->control));
1049 uval = (guint)strtoul(str_val, &p, pref->info.base);
1051 if (p == value || *p != '\0')
1052 return PREFS_SET_SYNTAX_ERR; /* number was bad */
1054 if (*pref->varp.uint != uval) {
1055 *pref_changed_p = TRUE;
1056 *pref->varp.uint = uval;
1061 bval = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(pref->control));
1062 if (*pref->varp.boolp != bval) {
1063 *pref_changed_p = TRUE;
1064 *pref->varp.boolp = bval;
1069 if (pref->info.enum_info.radio_buttons) {
1070 enumval = fetch_preference_radio_buttons_val((GtkWidget *)pref->control,
1071 pref->info.enum_info.enumvals);
1073 enumval = fetch_preference_option_menu_val((GtkWidget *)pref->control,
1074 pref->info.enum_info.enumvals);
1077 if (*pref->varp.enump != enumval) {
1078 *pref_changed_p = TRUE;
1079 *pref->varp.enump = enumval;
1086 str_val = gtk_entry_get_text(GTK_ENTRY(pref->control));
1087 if (strcmp(*pref->varp.string, str_val) != 0) {
1088 *pref_changed_p = TRUE;
1089 g_free((void *)*pref->varp.string);
1090 *pref->varp.string = g_strdup(str_val);
1099 str_val = gtk_entry_get_text(GTK_ENTRY(pref->control));
1100 ret = range_convert_str(&newrange, str_val, pref->info.max_value);
1101 if (ret != CVT_NO_ERROR)
1103 return PREFS_SET_SYNTAX_ERR; /* range was bad */
1105 return 0; /* XXX - should fail */
1108 if (!ranges_are_equal(*pref->varp.range, newrange)) {
1109 *pref_changed_p = TRUE;
1110 g_free(*pref->varp.range);
1111 *pref->varp.range = newrange;
1118 case PREF_STATIC_TEXT:
1124 /* currently not supported */
1127 g_assert_not_reached();
1134 module_prefs_fetch(module_t *module, gpointer user_data)
1136 gboolean *must_redissect_p = (gboolean *)user_data;
1138 /* Ignore any preferences with their own interface */
1139 if (!module->use_gui) {
1143 /* For all preferences in this module, fetch its value from this
1144 module's notebook page. Find out whether any of them changed. */
1145 module->prefs_changed = FALSE; /* assume none of them changed */
1146 prefs_pref_foreach(module, pref_fetch, &module->prefs_changed);
1148 /* If any of them changed, indicate that we must redissect and refilter
1149 the current capture (if we have one), as the preference change
1150 could cause packets to be dissected differently. */
1151 if (module->prefs_changed)
1152 *must_redissect_p = TRUE;
1154 return 0; /* keep fetching module preferences */
1159 * This function is used to apply changes and update the Wireless Toolbar
1160 * whenever we apply some changes to the WEP preferences
1163 prefs_airpcap_update(void)
1165 GtkWidget *decryption_cm;
1167 gboolean wireshark_decryption_was_enabled = FALSE;
1168 gboolean airpcap_decryption_was_enabled = FALSE;
1169 gboolean wireshark_decryption_is_now_enabled = FALSE;
1171 decryption_cm = GTK_WIDGET(g_object_get_data(G_OBJECT(wireless_tb),AIRPCAP_TOOLBAR_DECRYPTION_KEY));
1173 if (decryption_cm == NULL) {
1177 cur_active = gtk_combo_box_get_active(GTK_COMBO_BOX(decryption_cm));
1179 if (cur_active < 0) {
1183 switch(cur_active) {
1184 /* XXX - Don't use magic numbers here. cf airpcap_dlg.c:on_decryption_mode_cb_changed() */
1185 case 1: /* Wireshark */
1186 wireshark_decryption_was_enabled = TRUE;
1187 airpcap_decryption_was_enabled = FALSE;
1189 case 2: /* Driver */
1190 wireshark_decryption_was_enabled = FALSE;
1191 airpcap_decryption_was_enabled = TRUE;
1194 wireshark_decryption_was_enabled = FALSE;
1195 airpcap_decryption_was_enabled = FALSE;
1199 wireshark_decryption_is_now_enabled = wireshark_decryption_on();
1201 if (wireshark_decryption_is_now_enabled && airpcap_decryption_was_enabled)
1203 set_airpcap_decryption(FALSE);
1204 gtk_combo_box_set_active(GTK_COMBO_BOX(decryption_cm), 1);
1206 if (wireshark_decryption_is_now_enabled && !airpcap_decryption_was_enabled)
1208 set_airpcap_decryption(FALSE);
1209 gtk_combo_box_set_active(GTK_COMBO_BOX(decryption_cm), 1);
1211 else if (!wireshark_decryption_is_now_enabled && wireshark_decryption_was_enabled)
1213 if (airpcap_decryption_was_enabled)
1215 set_airpcap_decryption(TRUE);
1216 gtk_combo_box_set_active(GTK_COMBO_BOX(decryption_cm), 2);
1220 set_airpcap_decryption(FALSE);
1221 gtk_combo_box_set_active(GTK_COMBO_BOX(decryption_cm), 0);
1228 module_prefs_clean_stash(module_t *module, gpointer user_data _U_)
1230 /* Ignore any preferences with their own interface */
1231 if (!module->use_gui) {
1235 /* For all preferences in this module, clean up any cruft allocated for
1236 use by the GUI code. */
1237 prefs_pref_foreach(module, pref_clean_stash, NULL);
1238 return 0; /* keep cleaning modules */
1241 /* fetch all pref values from all pages */
1243 prefs_main_fetch_all(GtkWidget *dlg, gboolean *must_redissect)
1247 /* First, check that the values are all valid. */
1248 /* XXX - check the non-registered preferences too */
1249 switch (prefs_modules_foreach(module_prefs_check, (gpointer)&badpref)) {
1251 case PREFS_SET_SYNTAX_ERR:
1252 switch (badpref->type) {
1255 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1256 "The value for \"%s\" isn't a valid number.",
1261 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1262 "The value for \"%s\" isn't a valid range.",
1267 g_assert_not_reached();
1272 /* Fetch the preferences (i.e., make sure all the values set in all of
1273 the preferences panes have been copied to "prefs" and the registered
1275 gui_prefs_fetch((GtkWidget *)g_object_get_data(G_OBJECT(dlg), E_GUI_PAGE_KEY));
1276 layout_prefs_fetch((GtkWidget *)g_object_get_data(G_OBJECT(dlg), E_GUI_LAYOUT_PAGE_KEY));
1277 column_prefs_fetch((GtkWidget *)g_object_get_data(G_OBJECT(dlg), E_GUI_COLUMN_PAGE_KEY));
1278 font_color_prefs_fetch((GtkWidget *)g_object_get_data(G_OBJECT(dlg), E_GUI_FONT_COLORS_PAGE_KEY));
1282 /* Is WPcap loaded? */
1285 capture_prefs_fetch((GtkWidget *)g_object_get_data(G_OBJECT(dlg), E_CAPTURE_PAGE_KEY));
1289 #endif /* HAVE_LIBPCAP */
1290 filter_expressions_prefs_fetch((GtkWidget *)g_object_get_data(G_OBJECT(dlg),
1291 E_FILTER_EXPRESSIONS_PAGE_KEY));
1292 prefs_modules_foreach(module_prefs_fetch, must_redissect);
1297 /* apply all pref values to the real world */
1299 prefs_main_apply_all(GtkWidget *dlg, gboolean redissect)
1304 * Apply the protocol preferences first - "gui_prefs_apply()" could
1305 * cause redissection, and we have to make sure the protocol
1306 * preference changes have been fully applied.
1310 gui_prefs_apply((GtkWidget *)g_object_get_data(G_OBJECT(dlg), E_GUI_PAGE_KEY));
1311 layout_prefs_apply((GtkWidget *)g_object_get_data(G_OBJECT(dlg), E_GUI_LAYOUT_PAGE_KEY));
1312 column_prefs_apply((GtkWidget *)g_object_get_data(G_OBJECT(dlg), E_GUI_COLUMN_PAGE_KEY));
1313 font_color_prefs_apply((GtkWidget *)g_object_get_data(G_OBJECT(dlg), E_GUI_FONT_COLORS_PAGE_KEY), redissect);
1317 /* Is WPcap loaded? */
1320 capture_prefs_apply((GtkWidget *)g_object_get_data(G_OBJECT(dlg), E_CAPTURE_PAGE_KEY));
1324 #endif /* HAVE_LIBPCAP */
1326 /* show/hide the Save button - depending on setting */
1327 save_bt = (GtkWidget *)g_object_get_data(G_OBJECT(prefs_w), E_PREFSW_SAVE_BT_KEY);
1328 if (prefs.gui_use_pref_save) {
1329 gtk_widget_show(save_bt);
1331 gtk_widget_hide(save_bt);
1336 /* destroy all preferences ressources from all pages */
1338 prefs_main_destroy_all(GtkWidget *dlg)
1344 (frame = gtk_notebook_get_nth_page((GtkNotebook *)g_object_get_data(G_OBJECT(prefs_w), E_PREFSW_NOTEBOOK_KEY), page_num)) != NULL;
1346 if (g_object_get_data(G_OBJECT(frame), E_PAGE_ITER_KEY))
1347 gtk_tree_iter_free((GtkTreeIter *)g_object_get_data(G_OBJECT(frame), E_PAGE_ITER_KEY));
1350 gui_prefs_destroy((GtkWidget *)g_object_get_data(G_OBJECT(dlg), E_GUI_PAGE_KEY));
1351 layout_prefs_destroy((GtkWidget *)g_object_get_data(G_OBJECT(dlg), E_GUI_LAYOUT_PAGE_KEY));
1352 column_prefs_destroy((GtkWidget *)g_object_get_data(G_OBJECT(dlg), E_GUI_COLUMN_PAGE_KEY));
1353 font_color_prefs_destroy((GtkWidget *)g_object_get_data(G_OBJECT(dlg), E_GUI_FONT_COLORS_PAGE_KEY));
1357 /* Is WPcap loaded? */
1360 capture_prefs_destroy((GtkWidget *)g_object_get_data(G_OBJECT(dlg), E_CAPTURE_PAGE_KEY));
1364 #endif /* HAVE_LIBPCAP */
1366 /* Free up the saved preferences (both for "prefs" and for registered
1368 prefs_modules_foreach(module_prefs_clean_stash, NULL);
1372 module_prefs_copy(module_t *module, gpointer user_data _U_)
1374 /* Ignore any preferences with their own interface */
1375 if (!module->use_gui) {
1379 /* For all preferences in this module, (re)save current value */
1380 prefs_pref_foreach(module, pref_stash, NULL);
1381 return 0; /* continue making copies */
1384 /* Copy prefs to saved values so we can revert to these values */
1385 /* if the user selects Cancel. */
1386 static void prefs_copy(void) {
1387 prefs_modules_foreach(module_prefs_copy, NULL);
1391 overwrite_existing_prefs_cb(gpointer dialog _U_, gint btn, gpointer parent_w _U_)
1396 prefs.unknown_prefs = FALSE;
1398 case(ESD_BTN_DONT_SAVE):
1401 g_assert_not_reached();
1405 prefs_main_save(gpointer parent_w)
1407 if (prefs.unknown_prefs) {
1410 "Obsolete or unrecognized preferences have been detected and will be "
1411 "discarded when saving this profile. If you would like to preserve "
1412 "these preferences for a different Wireshark version, click "
1413 "'Continue without Saving' and save this profile under a different name.";
1415 if (prefs.saved_at_version) {
1416 dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_SAVE_DONTSAVE,
1417 "These preferences were last saved at version \"%s\".\n%s",
1418 prefs.saved_at_version, msg);
1420 dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_SAVE_DONTSAVE,
1424 simple_dialog_set_cb(dialog, overwrite_existing_prefs_cb, parent_w);
1431 prefs_main_ok_cb(GtkWidget *ok_bt _U_, gpointer parent_w)
1433 gboolean must_redissect = FALSE;
1435 if (!prefs_main_fetch_all((GtkWidget *)parent_w, &must_redissect))
1436 return; /* Errors in some preference setting - already reported */
1438 /* if we don't have a Save button, just save the settings now */
1439 if (!prefs.gui_use_pref_save) {
1440 prefs_main_save(parent_w);
1445 * Load the Wireshark decryption keys (just set) and save
1446 * the changes to the adapters' registry
1448 airpcap_load_decryption_keys(airpcap_if_list);
1451 prefs_main_apply_all((GtkWidget *)parent_w, must_redissect);
1453 /* Fill in capture options with values from the preferences */
1454 prefs_to_capture_opts();
1457 prefs_airpcap_update();
1460 /* Now destroy the "Preferences" dialog. */
1461 window_destroy(GTK_WIDGET(parent_w));
1463 if (must_redissect) {
1464 /* Redissect all the packets, and re-evaluate the display filter. */
1465 redissect_packets();
1466 redissect_all_packet_windows();
1472 prefs_main_apply_cb(GtkWidget *apply_bt _U_, gpointer parent_w)
1474 gboolean must_redissect = FALSE;
1476 if (!prefs_main_fetch_all((GtkWidget *)parent_w, &must_redissect))
1477 return; /* Errors in some preference setting - already reported */
1479 /* if we don't have a Save button, just save the settings now */
1480 if (!prefs.gui_use_pref_save) {
1481 prefs_main_save(parent_w);
1482 prefs_copy(); /* save prefs for reverting if Cancel */
1485 prefs_main_apply_all((GtkWidget *)parent_w, must_redissect);
1487 /* Fill in capture options with values from the preferences */
1488 prefs_to_capture_opts();
1491 prefs_airpcap_update();
1494 if (must_redissect) {
1495 /* Redissect all the packets, and re-evaluate the display filter. */
1496 redissect_packets();
1497 redissect_all_packet_windows();
1502 prefs_main_save_cb(GtkWidget *save_bt _U_, gpointer parent_w)
1504 gboolean must_redissect = FALSE;
1506 if (!prefs_main_fetch_all((GtkWidget *)parent_w, &must_redissect))
1507 return; /* Errors in some preference setting - already reported */
1509 prefs_main_save(parent_w);
1510 prefs_copy(); /* save prefs for reverting if Cancel */
1512 /* Now apply those preferences.
1513 XXX - should we do this? The user didn't click "OK" or "Apply".
1516 1) by saving the preferences they presumably indicate that they
1519 2) the next time they fire Wireshark up, those preferences will
1522 3) we'd have to buffer "must_redissect" so that if they do
1523 "Apply" after this, we know we have to redissect;
1525 4) we did apply the protocol preferences, at least, in the past. */
1526 prefs_main_apply_all((GtkWidget *)parent_w, must_redissect);
1528 /* Fill in capture options with values from the preferences */
1529 prefs_to_capture_opts();
1531 if (must_redissect) {
1532 /* Redissect all the packets, and re-evaluate the display filter. */
1533 redissect_packets();
1534 redissect_all_packet_windows();
1539 module_prefs_revert(module_t *module, gpointer user_data)
1541 gboolean *must_redissect_p = (gboolean *)user_data;
1543 /* Ignore any preferences with their own interface */
1544 if (!module->use_gui) {
1548 /* For all preferences in this module, revert its value to the value
1549 it had when we popped up the Preferences dialog. Find out whether
1550 this changes any of them. */
1551 module->prefs_changed = FALSE; /* assume none of them changed */
1552 prefs_pref_foreach(module, pref_unstash, &module->prefs_changed);
1554 /* If any of them changed, indicate that we must redissect and refilter
1555 the current capture (if we have one), as the preference change
1556 could cause packets to be dissected differently. */
1557 if (module->prefs_changed)
1558 *must_redissect_p = TRUE;
1559 return 0; /* keep processing modules */
1562 /* cancel button pressed, revert prefs to saved and exit dialog */
1564 prefs_main_cancel_cb(GtkWidget *cancel_bt _U_, gpointer parent_w)
1566 gboolean must_redissect = FALSE;
1568 /* Free up the current preferences and copy the saved preferences to the
1569 current preferences. */
1570 cfile.columns_changed = FALSE; /* [XXX: "columns_changed" should treally be stored in prefs struct ??] */
1572 /* Now revert the registered preferences. */
1573 prefs_modules_foreach(module_prefs_revert, &must_redissect);
1575 /* Now apply the reverted-to preferences. */
1576 prefs_main_apply_all((GtkWidget *)parent_w, must_redissect);
1578 window_destroy(GTK_WIDGET(parent_w));
1580 if (must_redissect) {
1581 /* Redissect all the packets, and re-evaluate the display filter. */
1582 redissect_packets();
1583 redissect_all_packet_windows();
1587 /* Treat this as a cancel, by calling "prefs_main_cancel_cb()" */
1589 prefs_main_delete_event_cb(GtkWidget *prefs_w_lcl, GdkEvent *event _U_,
1590 gpointer user_data _U_)
1592 prefs_main_cancel_cb(NULL, prefs_w_lcl);
1597 /* dialog *is* already destroyed, clean up memory and such */
1599 prefs_main_destroy_cb(GtkWidget *win _U_, gpointer parent_w)
1601 prefs_main_destroy_all((GtkWidget *)parent_w);
1603 /* Note that we no longer have a "Preferences" dialog box. */
1607 struct properties_data {
1613 module_search_properties(module_t *module, gpointer user_data)
1615 struct properties_data *p = (struct properties_data *)user_data;
1617 if (!module->use_gui) {
1618 /* This module uses its own GUI interface, so its not a part
1624 /* If this module has the specified title, remember it. */
1625 if (strcmp(module->title, p->title) == 0) {
1627 return 1; /* stops the search */
1630 if (prefs_module_has_submodules(module))
1631 return prefs_modules_foreach_submodules(module, module_search_properties, p);
1637 tree_expand_row(GtkTreeModel *model, GtkTreeView *tree_view, GtkTreeIter *iter)
1642 /* expand the parent first */
1643 if (gtk_tree_model_iter_parent(model, &parent, iter))
1644 tree_expand_row(model, tree_view, &parent);
1646 path = gtk_tree_model_get_path(model, iter);
1647 gtk_tree_view_expand_row(tree_view, path, FALSE);
1648 /*expand_tree(tree_view, &parent, NULL, NULL);*/
1650 gtk_tree_path_free(path);
1653 /* select a node in the tree view */
1654 /* XXX - this is almost 100% copied from byte_view_select() in proto_draw.c,
1655 * find a way to combine both to have a generic function for this */
1657 tree_select_node(GtkWidget *tree, prefs_tree_iter *iter)
1659 GtkTreeIter local_iter = *iter;
1660 GtkTreeView *tree_view = GTK_TREE_VIEW(tree);
1661 GtkTreeModel *model;
1662 GtkTreePath *first_path;
1664 model = gtk_tree_view_get_model(tree_view);
1666 /* Expand our field's row */
1667 first_path = gtk_tree_model_get_path(model, &local_iter);
1669 /* expand from the top down */
1670 tree_expand_row(model, tree_view, &local_iter);
1672 /* select our field's row */
1673 gtk_tree_selection_select_path(gtk_tree_view_get_selection(tree_view),
1676 /* And position the window so the selection is visible.
1677 * Position the selection in the middle of the viewable
1679 gtk_tree_view_scroll_to_cell(tree_view, first_path, NULL, TRUE, 0.5f, 0.0f);
1681 gtk_tree_path_free(first_path);
1685 /* search the corresponding protocol page of the currently selected field */
1687 properties_cb(GtkWidget *w, gpointer dummy)
1689 header_field_info *hfinfo;
1690 const gchar *title = NULL;
1691 struct properties_data p;
1695 module_t *page_module;
1697 if (cfile.finfo_selected == NULL) {
1698 const gchar *abbrev;
1700 /* There is no field selected, try use on top protocol */
1701 if (cfile.edt && cfile.edt->tree) {
1706 ga = proto_all_finfos(cfile.edt->tree);
1708 for (i = ga->len - 1; i > 0 ; i -= 1) {
1710 v = (field_info *)g_ptr_array_index (ga, i);
1713 if (!g_str_has_prefix(hfinfo->abbrev, "text") &&
1714 !g_str_has_prefix(hfinfo->abbrev, "_ws.expert") &&
1715 !g_str_has_prefix(hfinfo->abbrev, "_ws.malformed")) {
1716 if (hfinfo->parent == -1) {
1717 abbrev = hfinfo->abbrev;
1719 abbrev = proto_registrar_get_abbrev(hfinfo->parent);
1721 title = prefs_get_title_by_name(abbrev);
1727 /* Find the title for the protocol for the selected field. */
1728 hfinfo = cfile.finfo_selected->hfinfo;
1729 if (hfinfo->parent == -1)
1730 title = prefs_get_title_by_name(hfinfo->abbrev);
1732 title = prefs_get_title_by_name(proto_registrar_get_abbrev(hfinfo->parent));
1736 return; /* Couldn't find it. XXX - just crash? "Can't happen"? */
1738 /* Find the module for that protocol by searching for one with that title.
1739 XXX - should we just associate protocols with modules directly? */
1742 prefs_modules_foreach_submodules(protocols_module, module_search_properties,
1744 if (p.module == NULL) {
1745 /* We didn't find it - that protocol probably has no preferences. */
1749 /* Create a preferences window, or pop up an existing one. */
1750 if (prefs_w != NULL) {
1751 reactivate_window(prefs_w);
1756 /* Search all the pages in that window for the one with the specified
1759 (sw = gtk_notebook_get_nth_page((GtkNotebook *)g_object_get_data(G_OBJECT(prefs_w), E_PREFSW_NOTEBOOK_KEY), page_num)) != NULL;
1761 /* Get the frame from the scrollable window */
1762 frame = (GtkWidget *)g_object_get_data(G_OBJECT(sw), E_PAGESW_FRAME_KEY);
1763 /* Get the module for this page (non-protocol prefs don't have one). */
1765 page_module = (module_t *)g_object_get_data(G_OBJECT(frame), E_PAGE_MODULE_KEY);
1766 if (page_module != NULL) {
1767 if (page_module == p.module) {
1769 (GtkWidget *)g_object_get_data(G_OBJECT(prefs_w), E_PREFSW_TREE_KEY),
1770 (GtkTreeIter *)g_object_get_data(G_OBJECT(frame), E_PAGE_ITER_KEY));
1778 /* Prefs tree selection callback. The node data has been loaded with
1779 the proper notebook page to load. */
1781 prefs_tree_select_cb(GtkTreeSelection *sel, gpointer dummy _U_)
1784 GtkTreeModel *model;
1787 if (gtk_tree_selection_get_selected(sel, &model, &iter))
1789 gtk_tree_model_get(model, &iter, 1, &page, -1);
1791 gtk_notebook_set_current_page((GtkNotebook *)g_object_get_data(G_OBJECT(prefs_w), E_PREFSW_NOTEBOOK_KEY), page);
1803 * indent-tabs-mode: nil
1806 * ex: set shiftwidth=2 tabstop=8 expandtab:
1807 * :indentSize=2:tabSize=8:noTabs=true: