2 * Routines for handling preferences
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
31 #include <epan/packet.h>
32 #include <epan/prefs.h>
33 #include <epan/strutil.h>
34 #include <epan/prefs-int.h>
35 #include <epan/epan_dissect.h>
36 #include <epan/print.h>
39 #include "ui/preference_utils.h"
40 #include "ui/simple_dialog.h"
42 #include "ui/gtk/main.h"
43 #include "ui/gtk/prefs_column.h"
44 #include "ui/gtk/prefs_dlg.h"
45 #include "ui/gtk/prefs_filter_expressions.h"
46 #include "ui/gtk/prefs_font_color.h"
47 #include "ui/gtk/prefs_gui.h"
48 #include "ui/gtk/prefs_layout.h"
49 #include "ui/gtk/prefs_capture.h"
50 #include "ui/gtk/gui_utils.h"
51 #include "ui/gtk/dlg_utils.h"
52 #include "ui/gtk/stock_icons.h"
53 #include "ui/gtk/help_dlg.h"
54 #include "ui/gtk/keys.h"
55 #include "ui/gtk/uat_gui.h"
56 #include "ui/gtk/old-gtk-compat.h"
57 #include "ui/gtk/file_dlg.h"
58 #include "ui/gtk/dlg_utils.h"
59 #include "ui/gtk/packet_win.h"
63 #include "capture-wpcap.h"
67 #include "airpcap_loader.h"
68 #include "airpcap_gui_utils.h"
72 static void prefs_main_ok_cb(GtkWidget *, gpointer);
73 static void prefs_main_apply_cb(GtkWidget *, gpointer);
74 static void prefs_main_save_cb(GtkWidget *, gpointer);
75 static void prefs_main_cancel_cb(GtkWidget *, gpointer);
76 static gboolean prefs_main_delete_event_cb(GtkWidget *, GdkEvent *, gpointer);
77 static void prefs_main_destroy_cb(GtkWidget *, gpointer);
78 static void prefs_tree_select_cb(GtkTreeSelection *, gpointer);
80 static GtkWidget *create_preference_path_entry(GtkWidget *, int,
81 const gchar *, const gchar *, char *, gboolean);
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_FONT_COLORS_PAGE_KEY "gui_font_colors_options_page"
96 #define E_CAPTURE_PAGE_KEY "capture_options_page"
97 #define E_NAMERES_PAGE_KEY "nameres_options_page"
98 #define E_FILTER_EXPRESSIONS_PAGE_KEY "filter_expressions_page"
99 #define E_GRID_MODULE_KEY "grid_module"
102 * Keep a static pointer to the current "Preferences" window, if any, so that
103 * if somebody tries to do "Edit:Preferences" while there's already a
104 * "Preferences" window up, we just pop up the existing one, rather than
105 * creating a new one.
107 static GtkWidget *prefs_w;
119 pref_exists(pref_t *pref _U_, gpointer user_data _U_)
124 /* show a single preference on the GtkGrid of a preference page */
126 pref_show(pref_t *pref, gpointer user_data)
128 GtkWidget *main_grid = (GtkWidget *)user_data;
129 module_t *module = (module_t *)g_object_get_data(G_OBJECT(main_grid), E_GRID_MODULE_KEY);
131 const char *type_name = prefs_pref_type_name(pref);
137 /* Give this preference a label which is its title, followed by a colon,
138 and left-align it. */
140 label_len = strlen(title) + 2;
141 label_string = (char *)g_malloc(label_len);
142 g_strlcpy(label_string, title, label_len);
144 tooltip_txt = pref->description? g_strdup_printf("%s\n\nName: %s.%s\nType: %s",
148 type_name ? type_name : "Unknown"
152 * Sometimes we don't want to append a ':' after a static text string...
153 * If it is needed, we will specify it in the string itself.
155 if (pref->type != PREF_STATIC_TEXT)
156 g_strlcat(label_string, ":", label_len);
158 pref_stash(pref, NULL);
160 /* Save the current value of the preference, so that we can revert it if
161 the user does "Apply" and then "Cancel", and create the control for
162 editing the preference. */
163 switch (pref->type) {
166 /* XXX - there are no uint spinbuttons, so we can't use a spinbutton.
167 Even more annoyingly, even if there were, GLib doesn't define
168 G_MAXUINT - but I think ANSI C may define UINT_MAX, so we could
170 switch (pref->info.base) {
173 g_snprintf(uint_str, sizeof(uint_str), "%u", pref->stashed_val.uint);
177 g_snprintf(uint_str, sizeof(uint_str), "%o", pref->stashed_val.uint);
181 g_snprintf(uint_str, sizeof(uint_str), "%x", pref->stashed_val.uint);
184 pref->control = create_preference_entry(main_grid, pref->ordinal,
185 label_string, tooltip_txt,
190 pref->control = create_preference_check_button(main_grid, pref->ordinal,
191 label_string, tooltip_txt,
192 pref->stashed_val.boolval);
196 if (pref->info.enum_info.radio_buttons) {
197 /* Show it as radio buttons. */
198 pref->control = create_preference_radio_buttons(main_grid, pref->ordinal,
199 label_string, tooltip_txt,
200 pref->info.enum_info.enumvals,
201 pref->stashed_val.enumval);
203 /* Show it as an option menu. */
204 pref->control = create_preference_option_menu(main_grid, pref->ordinal,
205 label_string, tooltip_txt,
206 pref->info.enum_info.enumvals,
207 pref->stashed_val.enumval);
212 pref->control = create_preference_entry(main_grid, pref->ordinal,
213 label_string, tooltip_txt,
214 pref->stashed_val.string);
218 pref->control = create_preference_path_entry(main_grid, pref->ordinal,
221 pref->stashed_val.string, FALSE);
225 pref->control = create_preference_path_entry(main_grid, pref->ordinal,
228 pref->stashed_val.string, TRUE);
235 range_str_p = range_convert_range(*pref->varp.range);
236 pref->control = create_preference_entry(main_grid, pref->ordinal,
237 label_string, tooltip_txt,
242 case PREF_STATIC_TEXT:
244 pref->control = create_preference_static_text(main_grid, pref->ordinal,
245 label_string, tooltip_txt);
251 pref->control = create_preference_uat(main_grid, pref->ordinal,
252 label_string, tooltip_txt,
259 /* currently not supported */
262 g_assert_not_reached();
266 g_free(label_string);
271 #define prefs_tree_iter GtkTreeIter
273 /* add a page to the tree */
274 static prefs_tree_iter
275 prefs_tree_page_add(const gchar *title, gint page_nr,
276 gpointer store, prefs_tree_iter *parent_iter)
278 prefs_tree_iter iter;
280 gtk_tree_store_append((GtkTreeStore *)store, &iter, parent_iter);
281 gtk_tree_store_set((GtkTreeStore *)store, &iter, 0, title, 1, page_nr, -1);
285 /* add a page to the notebook */
287 prefs_nb_page_add(GtkWidget *notebook, const gchar *title _U_, GtkWidget *page, const char *page_key)
292 sw = gtk_scrolled_window_new(NULL, NULL);
293 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
296 frame = gtk_frame_new(NULL);
297 gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_NONE);
298 gtk_container_set_border_width(GTK_CONTAINER(frame), DLG_OUTER_MARGIN);
299 #if ! GTK_CHECK_VERSION(3,8,0)
300 gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(sw), frame);
302 gtk_container_add(GTK_CONTAINER(sw), frame);
304 gtk_widget_show(frame);
307 gtk_container_add(GTK_CONTAINER(frame), page);
308 g_object_set_data(G_OBJECT(prefs_w), page_key, page);
311 gtk_notebook_append_page (GTK_NOTEBOOK(notebook), sw, NULL);
316 #define MAX_TREE_NODE_NAME_LEN 64
318 /* show prefs page for each registered module (protocol) */
320 module_prefs_show(module_t *module, gpointer user_data)
322 struct ct_struct *cts = (struct ct_struct *)user_data;
323 struct ct_struct child_cts;
324 GtkWidget *main_vb, *main_grid, *frame, *main_sw;
325 gchar label_str[MAX_TREE_NODE_NAME_LEN];
329 if (!module->use_gui) {
330 /* This module uses its own GUI interface to modify its
331 * preferences, so ignore it
337 * Is this module an interior node, with modules underneath it?
339 if (!prefs_module_has_submodules(module)) {
342 * Does it have any preferences (other than possibly obsolete ones)?
344 if (prefs_pref_foreach(module, pref_exists, NULL) == 0) {
346 * No. Don't put the module into the preferences window,
347 * as there's nothing to show.
349 * XXX - we should do the same for interior ndes; if the module
350 * has no non-obsolete preferences *and* nothing under it has
351 * non-obsolete preferences, don't put it into the window.
358 * Add this module to the tree.
360 g_strlcpy(label_str, module->title, MAX_TREE_NODE_NAME_LEN);
361 model = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(cts->tree)));
363 if (module->parent == NULL)
364 gtk_tree_store_append(model, &iter, NULL);
366 gtk_tree_store_append(model, &iter, &cts->iter);
369 * Is this an interior node?
371 if (prefs_module_has_submodules(module)) {
375 gtk_tree_store_set(model, &iter, 0, label_str, 1, -1, -1);
378 * Walk the subtree and attach stuff to it.
381 child_cts.iter = iter;
382 prefs_modules_foreach_submodules(module, module_prefs_show, &child_cts);
384 /* keep the page count right */
385 cts->page = child_cts.page;
389 * We create pages for interior nodes even if they don't have
390 * preferences, so that we at least have something to show
391 * if the user clicks on them, even if it's empty.
394 /* Scrolled window */
395 main_sw = gtk_scrolled_window_new(NULL, NULL);
396 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(main_sw), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
399 frame = gtk_frame_new(NULL);
400 gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_NONE);
401 gtk_container_set_border_width(GTK_CONTAINER(frame), DLG_OUTER_MARGIN);
402 #if ! GTK_CHECK_VERSION(3,8,0)
403 gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(main_sw), frame);
405 gtk_container_add(GTK_CONTAINER(main_sw), frame);
407 g_object_set_data(G_OBJECT(main_sw), E_PAGESW_FRAME_KEY, frame);
409 /* Main vertical box */
410 main_vb = ws_gtk_box_new(GTK_ORIENTATION_VERTICAL, 5, FALSE);
411 gtk_container_set_border_width(GTK_CONTAINER(main_vb), 5);
412 gtk_container_add(GTK_CONTAINER(frame), main_vb);
415 main_grid = ws_gtk_grid_new();
416 gtk_box_pack_start(GTK_BOX(main_vb), main_grid, FALSE, FALSE, 0);
417 #if GTK_CHECK_VERSION(3,0,0)
418 gtk_widget_set_vexpand(GTK_WIDGET(main_grid), FALSE); /* Ignore VEXPAND requests from children */
420 ws_gtk_grid_set_row_spacing(GTK_GRID(main_grid), 10);
421 ws_gtk_grid_set_column_spacing(GTK_GRID(main_grid), 15);
423 /* Add items for each of the preferences */
424 g_object_set_data(G_OBJECT(main_grid), E_GRID_MODULE_KEY, module);
425 prefs_pref_foreach(module, pref_show, main_grid);
426 g_object_set_data(G_OBJECT(main_grid), E_GRID_MODULE_KEY, NULL);
428 /* Associate this module with the page's frame. */
429 g_object_set_data(G_OBJECT(frame), E_PAGE_MODULE_KEY, module);
431 /* Add the page to the notebook */
432 gtk_notebook_append_page(GTK_NOTEBOOK(cts->notebook), main_sw, NULL);
434 /* Attach the page to the tree item */
435 gtk_tree_store_set(model, &iter, 0, label_str, 1, cts->page, -1);
436 g_object_set_data(G_OBJECT(frame), E_PAGE_ITER_KEY, gtk_tree_iter_copy(&iter));
440 /* Show 'em what we got */
441 gtk_widget_show_all(main_sw);
447 /* show the dialog */
449 prefs_cb(GtkWidget *w, gpointer dummy)
451 prefs_page_cb (w, dummy, PREFS_PAGE_USER_INTERFACE);
455 prefs_page_cb(GtkWidget *w _U_, gpointer dummy _U_, PREFS_PAGE_E prefs_page)
457 GtkWidget *top_hb, *bbox, *prefs_nb, *ct_sb,
458 *ok_bt, *apply_bt, *save_bt, *cancel_bt, *help_bt;
459 gchar label_str[MAX_TREE_NODE_NAME_LEN];
460 struct ct_struct cts;
462 GtkTreeSelection *selection;
463 GtkCellRenderer *renderer;
464 GtkTreeViewColumn *column;
466 prefs_tree_iter gui_iter, layout_iter, columns_iter, capture_iter;
467 gint layout_page, columns_page;
468 gint capture_page = 0;
471 if (prefs_w != NULL) {
472 /* There's already a "Preferences" dialog box; reactivate it. */
473 reactivate_window(prefs_w);
477 prefs_w = dlg_conf_window_new("Wireshark: Preferences");
478 gtk_window_set_default_size(GTK_WINDOW(prefs_w), 400, 650);
481 * Unfortunately, we can't arrange that a GtkGrid widget wrap an event box
482 * around a grid row, so the spacing between the preference item's label
483 * and its control widgets is inactive and the tooltip doesn't pop up when
484 * the mouse is over it.
487 /* Container for each row of widgets */
488 cts.main_vb = ws_gtk_box_new(GTK_ORIENTATION_VERTICAL, 5, FALSE);
489 gtk_container_set_border_width(GTK_CONTAINER(cts.main_vb), 5);
490 gtk_container_add(GTK_CONTAINER(prefs_w), cts.main_vb);
491 gtk_widget_show(cts.main_vb);
493 /* Top row: Preferences tree and notebook */
494 top_hb = ws_gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 10, FALSE);
495 gtk_box_pack_start(GTK_BOX(cts.main_vb), top_hb, TRUE, TRUE, 0);
496 gtk_widget_show(top_hb);
498 /* scrolled window on the left for the categories tree */
499 ct_sb = scrolled_window_new(NULL, NULL);
500 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(ct_sb),
502 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(ct_sb),
503 GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
504 gtk_box_pack_start(GTK_BOX(top_hb), ct_sb, TRUE, TRUE, 0);
505 gtk_widget_show(ct_sb);
506 g_object_set_data(G_OBJECT(prefs_w), E_PREFSW_SCROLLW_KEY, ct_sb);
508 /* categories tree */
509 store = gtk_tree_store_new(2, G_TYPE_STRING, G_TYPE_INT);
510 cts.tree = tree_view_new(GTK_TREE_MODEL(store));
511 cts.iter.stamp = 0; /* mark this as the toplevel */
512 g_object_set_data(G_OBJECT(prefs_w), E_PREFSW_TREE_KEY, cts.tree);
513 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(cts.tree), FALSE);
514 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(cts.tree));
515 gtk_tree_selection_set_mode(selection, GTK_SELECTION_SINGLE);
516 renderer = gtk_cell_renderer_text_new();
517 col_offset = gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(cts.tree),
518 -1, "Name", renderer,
520 column = gtk_tree_view_get_column(GTK_TREE_VIEW(cts.tree),
522 gtk_tree_view_column_set_sizing(GTK_TREE_VIEW_COLUMN(column),
523 GTK_TREE_VIEW_COLUMN_AUTOSIZE);
524 g_signal_connect(selection, "changed", G_CALLBACK(prefs_tree_select_cb), NULL);
525 gtk_container_add(GTK_CONTAINER(ct_sb), cts.tree);
526 gtk_widget_show(cts.tree);
528 /* A notebook widget without tabs is used to flip between prefs */
529 prefs_nb = gtk_notebook_new();
530 g_object_set_data(G_OBJECT(prefs_w), E_PREFSW_NOTEBOOK_KEY, prefs_nb);
531 gtk_notebook_set_show_tabs(GTK_NOTEBOOK(prefs_nb), FALSE);
532 gtk_notebook_set_show_border(GTK_NOTEBOOK(prefs_nb), FALSE);
533 gtk_box_pack_start(GTK_BOX(top_hb), prefs_nb, TRUE, TRUE, 0);
534 gtk_widget_show(prefs_nb);
539 g_strlcpy(label_str, "User Interface", MAX_TREE_NODE_NAME_LEN);
540 prefs_nb_page_add(prefs_nb, label_str, gui_prefs_show(), E_GUI_PAGE_KEY);
541 gui_iter = prefs_tree_page_add(label_str, cts.page, store, NULL);
544 /* GUI layout prefs */
545 g_strlcpy(label_str, "Layout", MAX_TREE_NODE_NAME_LEN);
546 prefs_nb_page_add(prefs_nb, label_str, layout_prefs_show(), E_GUI_LAYOUT_PAGE_KEY);
547 layout_iter = prefs_tree_page_add(label_str, cts.page, store, &gui_iter);
548 layout_page = cts.page++;
550 /* GUI Column prefs */
551 g_strlcpy(label_str, "Columns", MAX_TREE_NODE_NAME_LEN);
552 prefs_nb_page_add(prefs_nb, label_str, column_prefs_show(prefs_w), E_GUI_COLUMN_PAGE_KEY);
553 columns_iter = prefs_tree_page_add(label_str, cts.page, store, &gui_iter);
554 columns_page = cts.page++;
556 /* GUI Colors prefs */
557 g_strlcpy(label_str, "Font and Colors", MAX_TREE_NODE_NAME_LEN);
558 prefs_nb_page_add(prefs_nb, label_str, font_color_prefs_show(), E_GUI_FONT_COLORS_PAGE_KEY);
559 prefs_tree_page_add(label_str, cts.page, store, &gui_iter);
562 /* select the main GUI page as the default page and expand its children */
563 gtk_tree_selection_select_iter(selection, &gui_iter);
564 /* (expand will only take effect, when at least one child exists) */
565 gtk_tree_view_expand_all(GTK_TREE_VIEW(cts.tree));
569 /* Is WPcap loaded? */
573 g_strlcpy(label_str, "Capture", MAX_TREE_NODE_NAME_LEN);
574 prefs_nb_page_add(prefs_nb, label_str, capture_prefs_show(), E_CAPTURE_PAGE_KEY);
575 capture_iter = prefs_tree_page_add(label_str, cts.page, store, NULL);
576 capture_page = cts.page++;
580 #endif /* HAVE_LIBPCAP */
582 /* Saved filter prefs */
583 g_strlcpy(label_str, "Filter Expressions", MAX_TREE_NODE_NAME_LEN);
584 prefs_nb_page_add(prefs_nb, label_str, filter_expressions_prefs_show(),
585 E_FILTER_EXPRESSIONS_PAGE_KEY);
586 prefs_tree_page_add(label_str, cts.page, store, NULL);
589 /* Registered prefs */
590 cts.notebook = prefs_nb;
592 prefs_modules_foreach_submodules(NULL, module_prefs_show, &cts);
594 /* Button row: OK and alike buttons */
595 bbox = dlg_button_row_new(GTK_STOCK_HELP, GTK_STOCK_OK, GTK_STOCK_APPLY, GTK_STOCK_SAVE, GTK_STOCK_CANCEL, NULL);
596 gtk_box_pack_start(GTK_BOX(cts.main_vb), bbox, FALSE, FALSE, 0);
597 gtk_widget_show(bbox);
599 ok_bt = (GtkWidget *)g_object_get_data(G_OBJECT(bbox), GTK_STOCK_OK);
600 g_signal_connect(ok_bt, "clicked", G_CALLBACK(prefs_main_ok_cb), prefs_w);
602 apply_bt = (GtkWidget *)g_object_get_data(G_OBJECT(bbox), GTK_STOCK_APPLY);
603 g_signal_connect(apply_bt, "clicked", G_CALLBACK(prefs_main_apply_cb), prefs_w);
605 save_bt = (GtkWidget *)g_object_get_data(G_OBJECT(bbox), GTK_STOCK_SAVE);
606 g_signal_connect(save_bt, "clicked", G_CALLBACK(prefs_main_save_cb), prefs_w);
607 g_object_set_data(G_OBJECT(prefs_w), E_PREFSW_SAVE_BT_KEY, save_bt);
609 cancel_bt = (GtkWidget *)g_object_get_data(G_OBJECT(bbox), GTK_STOCK_CANCEL);
610 g_signal_connect(cancel_bt, "clicked", G_CALLBACK(prefs_main_cancel_cb), prefs_w);
611 window_set_cancel_button(prefs_w, cancel_bt, NULL);
613 gtk_widget_grab_default(ok_bt);
615 help_bt = (GtkWidget *)g_object_get_data(G_OBJECT(bbox), GTK_STOCK_HELP);
616 g_signal_connect(help_bt, "clicked", G_CALLBACK(topic_cb), (gpointer)HELP_PREFERENCES_DIALOG);
618 g_signal_connect(prefs_w, "delete_event", G_CALLBACK(prefs_main_delete_event_cb), NULL);
619 g_signal_connect(prefs_w, "destroy", G_CALLBACK(prefs_main_destroy_cb), prefs_w);
621 gtk_widget_show(prefs_w);
623 /* hide the Save button if the user uses implicit save */
624 if (!prefs.gui_use_pref_save) {
625 gtk_widget_hide(save_bt);
628 window_present(prefs_w);
630 switch (prefs_page) {
631 case PREFS_PAGE_LAYOUT:
632 gtk_tree_selection_select_iter(selection, &layout_iter);
633 gtk_notebook_set_current_page((GtkNotebook *)g_object_get_data(G_OBJECT(prefs_w), E_PREFSW_NOTEBOOK_KEY), layout_page);
635 case PREFS_PAGE_COLUMNS:
636 gtk_tree_selection_select_iter(selection, &columns_iter);
637 gtk_notebook_set_current_page((GtkNotebook *)g_object_get_data(G_OBJECT(prefs_w), E_PREFSW_NOTEBOOK_KEY), columns_page);
639 case PREFS_PAGE_CAPTURE:
641 gtk_tree_selection_select_iter(selection, &capture_iter);
642 gtk_notebook_set_current_page((GtkNotebook *)g_object_get_data(G_OBJECT(prefs_w), E_PREFSW_NOTEBOOK_KEY), capture_page);
646 /* Not implemented yet */
650 g_object_unref(G_OBJECT(store));
654 set_option_label(GtkWidget *main_grid, int grid_position,
655 const gchar *label_text, const gchar *tooltip_text)
658 GtkWidget *event_box;
660 label = gtk_label_new(label_text);
661 gtk_misc_set_alignment(GTK_MISC(label), 1.0f, 0.5f);
662 gtk_widget_show(label);
664 event_box = gtk_event_box_new();
665 gtk_event_box_set_visible_window (GTK_EVENT_BOX(event_box), FALSE);
666 ws_gtk_grid_attach_defaults(GTK_GRID(main_grid), event_box, 0, grid_position, 1, 1);
667 if (tooltip_text != NULL)
668 gtk_widget_set_tooltip_text(event_box, tooltip_text);
669 gtk_container_add(GTK_CONTAINER(event_box), label);
670 gtk_widget_show(event_box);
674 create_preference_check_button(GtkWidget *main_grid, int grid_position,
675 const gchar *label_text, const gchar *tooltip_text, gboolean active)
677 GtkWidget *check_box;
679 set_option_label(main_grid, grid_position, label_text, tooltip_text);
681 check_box = gtk_check_button_new();
682 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check_box), active);
683 ws_gtk_grid_attach_defaults(GTK_GRID(main_grid), check_box, 1, grid_position, 1, 1);
684 if (tooltip_text != NULL)
685 gtk_widget_set_tooltip_text(check_box, tooltip_text);
691 create_preference_radio_buttons(GtkWidget *main_grid, int grid_position,
692 const gchar *label_text, const gchar *tooltip_text,
693 const enum_val_t *enumvals, gint current_val)
695 GtkWidget *radio_button_hbox, *button = NULL;
698 const enum_val_t *enum_valp;
699 GtkWidget *event_box;
701 set_option_label(main_grid, grid_position, label_text, tooltip_text);
703 radio_button_hbox = ws_gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0, FALSE);
705 for (enum_valp = enumvals, idx = 0; enum_valp->name != NULL;
706 enum_valp++, idx++) {
707 button = gtk_radio_button_new_with_label(rb_group,
708 enum_valp->description);
709 gtk_widget_show(button);
710 rb_group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(button));
711 gtk_box_pack_start(GTK_BOX(radio_button_hbox), button, FALSE,
713 if (enum_valp->value == current_val) {
714 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button),
718 gtk_widget_show(radio_button_hbox);
720 event_box = gtk_event_box_new();
721 gtk_event_box_set_visible_window (GTK_EVENT_BOX(event_box), FALSE);
722 gtk_container_add(GTK_CONTAINER(event_box), radio_button_hbox);
723 ws_gtk_grid_attach_defaults(GTK_GRID(main_grid), event_box, 1, grid_position, 1, 1);
724 if (tooltip_text != NULL)
725 gtk_widget_set_tooltip_text(event_box, tooltip_text);
726 gtk_widget_show(event_box);
729 * It doesn't matter which of the buttons we return - we fetch
730 * the value by looking at the entire radio button group to
731 * which it belongs, and we can get that from any button.
737 label_to_enum_val(GtkWidget *label, const enum_val_t *enumvals)
739 const gchar *label_string;
742 /* Get the label's text, and translate it to a value.
743 We match only the descriptions, as those are what appear in
744 the option menu items or as labels for radio buttons.
745 We fail if we don't find a match, as that "can't happen". */
746 label_string = gtk_label_get_text(GTK_LABEL(label));
748 for (i = 0; enumvals[i].name != NULL; i++) {
749 if (g_ascii_strcasecmp(label_string, enumvals[i].description) == 0) {
750 return enumvals[i].value;
753 g_assert_not_reached();
758 fetch_preference_radio_buttons_val(GtkWidget *button,
759 const enum_val_t *enumvals)
765 * Go through the list of of radio buttons in the button's group,
766 * and find the first one that's active.
768 rb_group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(button));
770 for (rb_entry = rb_group; rb_entry != NULL;
771 rb_entry = g_slist_next(rb_entry)) {
772 button = (GtkWidget *)rb_entry->data;
773 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button)))
777 /* OK, now return the value corresponding to that button's label. */
778 return label_to_enum_val(gtk_bin_get_child(GTK_BIN(button)), enumvals);
782 create_preference_option_menu(GtkWidget *main_grid, int grid_position,
783 const gchar *label_text, const gchar *tooltip_text,
784 const enum_val_t *enumvals, gint current_val)
786 GtkWidget *menu_box, *combo_box;
788 const enum_val_t *enum_valp;
789 GtkWidget *event_box;
791 set_option_label(main_grid, grid_position, label_text, tooltip_text);
793 /* Create a menu from the enumvals */
794 combo_box = gtk_combo_box_text_new();
795 if (tooltip_text != NULL)
796 gtk_widget_set_tooltip_text(combo_box, tooltip_text);
798 for (enum_valp = enumvals, idx = 0; enum_valp->name != NULL;
799 enum_valp++, idx++) {
800 gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo_box), enum_valp->description);
801 if (enum_valp->value == current_val)
804 /* Set the current value active */
805 gtk_combo_box_set_active(GTK_COMBO_BOX(combo_box), menu_idx);
808 * Put the combo box in an hbox, so that it's only as wide
809 * as the widest entry, rather than being as wide as the grid
812 menu_box = ws_gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0, FALSE);
813 gtk_box_pack_start(GTK_BOX(menu_box), combo_box, FALSE, FALSE, 0);
815 event_box = gtk_event_box_new();
816 gtk_event_box_set_visible_window (GTK_EVENT_BOX(event_box), FALSE);
817 ws_gtk_grid_attach_defaults(GTK_GRID(main_grid), event_box, 1, grid_position, 1, 1);
818 if (tooltip_text != NULL)
819 gtk_widget_set_tooltip_text(event_box, tooltip_text);
820 gtk_container_add(GTK_CONTAINER(event_box), menu_box);
826 fetch_preference_option_menu_val(GtkWidget *combo_box, const enum_val_t *enumvals)
829 * OK, now return the value corresponding to the label for the
830 * currently active entry in the combo box.
834 i = gtk_combo_box_get_active (GTK_COMBO_BOX(combo_box));
836 return enumvals[i].value;
840 create_preference_entry(GtkWidget *main_grid, int grid_position,
841 const gchar *label_text, const gchar *tooltip_text, char *value)
845 set_option_label(main_grid, grid_position, label_text, tooltip_text);
847 entry = gtk_entry_new();
849 gtk_entry_set_text(GTK_ENTRY(entry), value);
850 ws_gtk_grid_attach_defaults(GTK_GRID(main_grid), entry, 1, grid_position, 1, 1);
851 if (tooltip_text != NULL)
852 gtk_widget_set_tooltip_text(entry, tooltip_text);
853 gtk_widget_show(entry);
859 preference_filename_entry_cb(GtkWidget *button, GtkWidget *filename_te)
861 /* XXX - use a better browser dialog title */
862 file_selection_browse(button, filename_te, "Wireshark: File preference",
863 FILE_SELECTION_READ_BROWSE);
867 preference_dirname_entry_cb(GtkWidget *button, GtkWidget *filename_te)
869 /* XXX - use a better browser dialog title */
870 file_selection_browse(button, filename_te, "Wireshark: Directory preference",
871 FILE_SELECTION_CREATE_FOLDER);
875 create_preference_path_entry(GtkWidget *main_grid, int grid_position,
876 const gchar *label_text, const gchar *tooltip_text, char *value, gboolean dir_only)
879 GtkWidget *button, *file_bt_hb;
881 set_option_label(main_grid, grid_position, label_text, tooltip_text);
882 file_bt_hb = ws_gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0, FALSE);
883 ws_gtk_grid_attach_defaults(GTK_GRID(main_grid), file_bt_hb, 1, grid_position, 1, 1);
884 gtk_widget_show(file_bt_hb);
886 button = gtk_button_new_from_stock(WIRESHARK_STOCK_BROWSE);
887 gtk_box_pack_end(GTK_BOX(file_bt_hb), button, FALSE, FALSE, 0);
888 gtk_widget_show(button);
890 entry = gtk_entry_new();
891 gtk_box_pack_start(GTK_BOX(file_bt_hb), entry, TRUE, TRUE, 0);
893 gtk_entry_set_text(GTK_ENTRY(entry), value);
894 if (tooltip_text != NULL)
895 gtk_widget_set_tooltip_text(entry, tooltip_text);
896 gtk_widget_show(entry);
899 g_signal_connect(button, "clicked", G_CALLBACK(preference_dirname_entry_cb), entry);
901 g_signal_connect(button, "clicked", G_CALLBACK(preference_filename_entry_cb), entry);
908 create_preference_static_text(GtkWidget *main_grid, int grid_position,
909 const gchar *label_text, const gchar *tooltip_text)
913 if (label_text != NULL)
914 label = gtk_label_new(label_text);
916 label = gtk_label_new("");
917 ws_gtk_grid_attach_defaults(GTK_GRID(main_grid), label, 0, grid_position, 2, 1);
918 if (tooltip_text != NULL)
919 gtk_widget_set_tooltip_text(label, tooltip_text);
920 gtk_widget_show(label);
926 create_preference_uat(GtkWidget *main_grid, int grid_position,
927 const gchar *label_text, const gchar *tooltip_text, void* uat)
931 set_option_label(main_grid, grid_position, label_text, tooltip_text);
933 button = gtk_button_new_from_stock(WIRESHARK_STOCK_EDIT);
935 g_signal_connect(button, "clicked", G_CALLBACK(uat_window_cb), uat);
937 ws_gtk_grid_attach_defaults(GTK_GRID(main_grid), button, 1, grid_position, 1, 1);
938 if (tooltip_text != NULL)
939 gtk_widget_set_tooltip_text(button, tooltip_text);
940 gtk_widget_show(button);
947 pref_check(pref_t *pref, gpointer user_data)
951 pref_t **badpref = (pref_t **)user_data;
953 /* Fetch the value of the preference, and check whether it's valid. */
954 switch (pref->type) {
957 str_val = gtk_entry_get_text(GTK_ENTRY(pref->control));
960 /* XXX: The following ugly hack prevents a gcc warning
961 "ignoring return value of 'strtoul', declared with attribute warn_unused_result"
962 which can occur when using certain gcc configurations (see -D_FORTIFY_SOURCE).
963 A dummy variable is not used because when using gcc 4.6 with -Wextra a
964 "set but not used [-Wunused-but-set-variable]" warning will occur.
965 (Coverity & CLang apparently do not object to this hack).
968 "... perhaps either using spin buttons for numeric preferences, or otherwise making
969 it impossible to type something that's not a number into the GUI for those preferences,
970 and thus avoiding the need to check whether it's a valid number, would also be a good idea."
973 if (strtoul(str_val, &p, pref->info.base)){}
974 if (p == str_val || *p != '\0' || errno != 0) {
976 return PREFS_SET_SYNTAX_ERR; /* number was bad */
981 /* Value can't be bad. */
985 /* Value can't be bad. */
991 /* Value can't be bad. */
995 str_val = gtk_entry_get_text(GTK_ENTRY(pref->control));
997 if (strlen(str_val) != 0) {
1000 if (range_convert_str(&newrange, str_val, pref->info.max_value) != CVT_NO_ERROR) {
1002 return PREFS_SET_SYNTAX_ERR; /* range was bad */
1008 case PREF_STATIC_TEXT:
1010 /* Value can't be bad. */
1015 /* currently not supported */
1018 g_assert_not_reached();
1025 module_prefs_check(module_t *module, gpointer user_data)
1027 /* Ignore any preferences with their own interface */
1028 if (!module->use_gui) {
1032 /* For all preferences in this module, fetch its value from this
1033 module's notebook page and check whether it's valid. */
1034 return prefs_pref_foreach(module, pref_check, user_data);
1038 pref_fetch(pref_t *pref, gpointer user_data)
1040 const char *str_val;
1045 gboolean *pref_changed_p = (gboolean *)user_data;
1047 /* Fetch the value of the preference, and set the appropriate variable
1049 switch (pref->type) {
1052 str_val = gtk_entry_get_text(GTK_ENTRY(pref->control));
1053 uval = (guint)strtoul(str_val, &p, pref->info.base);
1055 if (p == value || *p != '\0')
1056 return PREFS_SET_SYNTAX_ERR; /* number was bad */
1058 if (*pref->varp.uint != uval) {
1059 *pref_changed_p = TRUE;
1060 *pref->varp.uint = uval;
1065 bval = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(pref->control));
1066 if (*pref->varp.boolp != bval) {
1067 *pref_changed_p = TRUE;
1068 *pref->varp.boolp = bval;
1073 if (pref->info.enum_info.radio_buttons) {
1074 enumval = fetch_preference_radio_buttons_val((GtkWidget *)pref->control,
1075 pref->info.enum_info.enumvals);
1077 enumval = fetch_preference_option_menu_val((GtkWidget *)pref->control,
1078 pref->info.enum_info.enumvals);
1081 if (*pref->varp.enump != enumval) {
1082 *pref_changed_p = TRUE;
1083 *pref->varp.enump = enumval;
1090 str_val = gtk_entry_get_text(GTK_ENTRY(pref->control));
1091 if (strcmp(*pref->varp.string, str_val) != 0) {
1092 *pref_changed_p = TRUE;
1093 g_free((void *)*pref->varp.string);
1094 *pref->varp.string = g_strdup(str_val);
1103 str_val = gtk_entry_get_text(GTK_ENTRY(pref->control));
1104 ret = range_convert_str(&newrange, str_val, pref->info.max_value);
1105 if (ret != CVT_NO_ERROR)
1107 return PREFS_SET_SYNTAX_ERR; /* range was bad */
1109 return 0; /* XXX - should fail */
1112 if (!ranges_are_equal(*pref->varp.range, newrange)) {
1113 *pref_changed_p = TRUE;
1114 g_free(*pref->varp.range);
1115 *pref->varp.range = newrange;
1122 case PREF_STATIC_TEXT:
1128 /* currently not supported */
1131 g_assert_not_reached();
1138 module_prefs_fetch(module_t *module, gpointer user_data)
1140 gboolean *must_redissect_p = (gboolean *)user_data;
1142 /* Ignore any preferences with their own interface */
1143 if (!module->use_gui) {
1147 /* For all preferences in this module, fetch its value from this
1148 module's notebook page. Find out whether any of them changed. */
1149 module->prefs_changed = FALSE; /* assume none of them changed */
1150 prefs_pref_foreach(module, pref_fetch, &module->prefs_changed);
1152 /* If any of them changed, indicate that we must redissect and refilter
1153 the current capture (if we have one), as the preference change
1154 could cause packets to be dissected differently. */
1155 if (module->prefs_changed)
1156 *must_redissect_p = TRUE;
1158 return 0; /* keep fetching module preferences */
1163 * This function is used to apply changes and update the Wireless Toolbar
1164 * whenever we apply some changes to the WEP preferences
1167 prefs_airpcap_update(void)
1169 GtkWidget *decryption_cm;
1171 gboolean wireshark_decryption_was_enabled = FALSE;
1172 gboolean airpcap_decryption_was_enabled = FALSE;
1173 gboolean wireshark_decryption_is_now_enabled = FALSE;
1175 decryption_cm = GTK_WIDGET(g_object_get_data(G_OBJECT(wireless_tb),AIRPCAP_TOOLBAR_DECRYPTION_KEY));
1177 if (decryption_cm == NULL) {
1181 cur_active = gtk_combo_box_get_active(GTK_COMBO_BOX(decryption_cm));
1183 if (cur_active < 0) {
1187 switch(cur_active) {
1188 /* XXX - Don't use magic numbers here. cf airpcap_dlg.c:on_decryption_mode_cb_changed() */
1189 case 1: /* Wireshark */
1190 wireshark_decryption_was_enabled = TRUE;
1191 airpcap_decryption_was_enabled = FALSE;
1193 case 2: /* Driver */
1194 wireshark_decryption_was_enabled = FALSE;
1195 airpcap_decryption_was_enabled = TRUE;
1198 wireshark_decryption_was_enabled = FALSE;
1199 airpcap_decryption_was_enabled = FALSE;
1203 wireshark_decryption_is_now_enabled = wireshark_decryption_on();
1205 if (wireshark_decryption_is_now_enabled && airpcap_decryption_was_enabled)
1207 set_airpcap_decryption(FALSE);
1208 gtk_combo_box_set_active(GTK_COMBO_BOX(decryption_cm), 1);
1210 if (wireshark_decryption_is_now_enabled && !airpcap_decryption_was_enabled)
1212 set_airpcap_decryption(FALSE);
1213 gtk_combo_box_set_active(GTK_COMBO_BOX(decryption_cm), 1);
1215 else if (!wireshark_decryption_is_now_enabled && wireshark_decryption_was_enabled)
1217 if (airpcap_decryption_was_enabled)
1219 set_airpcap_decryption(TRUE);
1220 gtk_combo_box_set_active(GTK_COMBO_BOX(decryption_cm), 2);
1224 set_airpcap_decryption(FALSE);
1225 gtk_combo_box_set_active(GTK_COMBO_BOX(decryption_cm), 0);
1232 module_prefs_clean_stash(module_t *module, gpointer user_data _U_)
1234 /* Ignore any preferences with their own interface */
1235 if (!module->use_gui) {
1239 /* For all preferences in this module, clean up any cruft allocated for
1240 use by the GUI code. */
1241 prefs_pref_foreach(module, pref_clean_stash, NULL);
1242 return 0; /* keep cleaning modules */
1245 /* fetch all pref values from all pages */
1247 prefs_main_fetch_all(GtkWidget *dlg, gboolean *must_redissect)
1251 /* First, check that the values are all valid. */
1252 /* XXX - check the non-registered preferences too */
1253 switch (prefs_modules_foreach(module_prefs_check, (gpointer)&badpref)) {
1255 case PREFS_SET_SYNTAX_ERR:
1256 switch (badpref->type) {
1259 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1260 "The value for \"%s\" isn't a valid number.",
1265 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1266 "The value for \"%s\" isn't a valid range.",
1271 g_assert_not_reached();
1276 /* Fetch the preferences (i.e., make sure all the values set in all of
1277 the preferences panes have been copied to "prefs" and the registered
1279 gui_prefs_fetch((GtkWidget *)g_object_get_data(G_OBJECT(dlg), E_GUI_PAGE_KEY));
1280 layout_prefs_fetch((GtkWidget *)g_object_get_data(G_OBJECT(dlg), E_GUI_LAYOUT_PAGE_KEY));
1281 column_prefs_fetch((GtkWidget *)g_object_get_data(G_OBJECT(dlg), E_GUI_COLUMN_PAGE_KEY));
1282 font_color_prefs_fetch((GtkWidget *)g_object_get_data(G_OBJECT(dlg), E_GUI_FONT_COLORS_PAGE_KEY));
1286 /* Is WPcap loaded? */
1289 capture_prefs_fetch((GtkWidget *)g_object_get_data(G_OBJECT(dlg), E_CAPTURE_PAGE_KEY));
1293 #endif /* HAVE_LIBPCAP */
1294 filter_expressions_prefs_fetch((GtkWidget *)g_object_get_data(G_OBJECT(dlg),
1295 E_FILTER_EXPRESSIONS_PAGE_KEY));
1296 prefs_modules_foreach(module_prefs_fetch, must_redissect);
1301 /* apply all pref values to the real world */
1303 prefs_main_apply_all(GtkWidget *dlg, gboolean redissect)
1308 * Apply the protocol preferences first - "gui_prefs_apply()" could
1309 * cause redissection, and we have to make sure the protocol
1310 * preference changes have been fully applied.
1314 gui_prefs_apply((GtkWidget *)g_object_get_data(G_OBJECT(dlg), E_GUI_PAGE_KEY));
1315 layout_prefs_apply((GtkWidget *)g_object_get_data(G_OBJECT(dlg), E_GUI_LAYOUT_PAGE_KEY));
1316 column_prefs_apply((GtkWidget *)g_object_get_data(G_OBJECT(dlg), E_GUI_COLUMN_PAGE_KEY));
1317 font_color_prefs_apply((GtkWidget *)g_object_get_data(G_OBJECT(dlg), E_GUI_FONT_COLORS_PAGE_KEY), redissect);
1321 /* Is WPcap loaded? */
1324 capture_prefs_apply((GtkWidget *)g_object_get_data(G_OBJECT(dlg), E_CAPTURE_PAGE_KEY));
1328 #endif /* HAVE_LIBPCAP */
1330 /* show/hide the Save button - depending on setting */
1331 save_bt = (GtkWidget *)g_object_get_data(G_OBJECT(prefs_w), E_PREFSW_SAVE_BT_KEY);
1332 if (prefs.gui_use_pref_save) {
1333 gtk_widget_show(save_bt);
1335 gtk_widget_hide(save_bt);
1340 /* destroy all preferences ressources from all pages */
1342 prefs_main_destroy_all(GtkWidget *dlg)
1348 (frame = gtk_notebook_get_nth_page((GtkNotebook *)g_object_get_data(G_OBJECT(prefs_w), E_PREFSW_NOTEBOOK_KEY), page_num)) != NULL;
1350 if (g_object_get_data(G_OBJECT(frame), E_PAGE_ITER_KEY))
1351 gtk_tree_iter_free((GtkTreeIter *)g_object_get_data(G_OBJECT(frame), E_PAGE_ITER_KEY));
1354 gui_prefs_destroy((GtkWidget *)g_object_get_data(G_OBJECT(dlg), E_GUI_PAGE_KEY));
1355 layout_prefs_destroy((GtkWidget *)g_object_get_data(G_OBJECT(dlg), E_GUI_LAYOUT_PAGE_KEY));
1356 column_prefs_destroy((GtkWidget *)g_object_get_data(G_OBJECT(dlg), E_GUI_COLUMN_PAGE_KEY));
1357 font_color_prefs_destroy((GtkWidget *)g_object_get_data(G_OBJECT(dlg), E_GUI_FONT_COLORS_PAGE_KEY));
1361 /* Is WPcap loaded? */
1364 capture_prefs_destroy((GtkWidget *)g_object_get_data(G_OBJECT(dlg), E_CAPTURE_PAGE_KEY));
1368 #endif /* HAVE_LIBPCAP */
1370 /* Free up the saved preferences (both for "prefs" and for registered
1372 prefs_modules_foreach(module_prefs_clean_stash, NULL);
1376 module_prefs_copy(module_t *module, gpointer user_data _U_)
1378 /* Ignore any preferences with their own interface */
1379 if (!module->use_gui) {
1383 /* For all preferences in this module, (re)save current value */
1384 prefs_pref_foreach(module, pref_stash, NULL);
1385 return 0; /* continue making copies */
1388 /* Copy prefs to saved values so we can revert to these values */
1389 /* if the user selects Cancel. */
1390 static void prefs_copy(void) {
1391 prefs_modules_foreach(module_prefs_copy, NULL);
1395 overwrite_existing_prefs_cb(gpointer dialog _U_, gint btn, gpointer parent_w)
1400 prefs.unknown_prefs = FALSE;
1402 case(ESD_BTN_DONT_SAVE):
1405 g_assert_not_reached();
1409 prefs_main_save(gpointer parent_w)
1411 if (prefs.unknown_prefs) {
1414 gchar *msg1 = "These preferences were last saved at version ";
1415 gchar *msg2 = "Obsolete or unrecognized preferences have been detected. "
1416 "If you plan to use this profile with ";
1417 gchar *msg3 = "that version of Wireshark, ";
1418 gchar *msg4 = "an older or nonstandard Wireshark version, ";
1419 gchar *msg5 = "click 'Continue without Saving' and save this profile under a another name.\n";
1421 if (prefs.saved_at_version) {
1422 gulong tot_msg_len = 246 + (gulong)strlen(prefs.saved_at_version) + 1;
1424 msg = (gchar *)g_malloc(tot_msg_len);
1425 g_snprintf(msg, tot_msg_len, "%s\"%s\". %s%s%s",
1426 msg1, prefs.saved_at_version, msg2, msg3, msg5);
1427 dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_SAVE_DONTSAVE, msg);
1429 msg = (gchar *)g_malloc(214);
1431 g_snprintf(msg, 214, "%s%s%s", msg2, msg4, msg5);
1432 dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_SAVE_DONTSAVE, msg);
1435 simple_dialog_set_cb(dialog, overwrite_existing_prefs_cb, parent_w);
1444 prefs_main_ok_cb(GtkWidget *ok_bt _U_, gpointer parent_w)
1446 gboolean must_redissect = FALSE;
1448 if (!prefs_main_fetch_all((GtkWidget *)parent_w, &must_redissect))
1449 return; /* Errors in some preference setting - already reported */
1451 /* if we don't have a Save button, just save the settings now */
1452 if (!prefs.gui_use_pref_save) {
1453 prefs_main_save(parent_w);
1458 * Load the Wireshark decryption keys (just set) and save
1459 * the changes to the adapters' registry
1461 airpcap_load_decryption_keys(airpcap_if_list);
1464 prefs_main_apply_all((GtkWidget *)parent_w, must_redissect);
1466 /* Fill in capture options with values from the preferences */
1467 prefs_to_capture_opts();
1470 prefs_airpcap_update();
1473 /* Now destroy the "Preferences" dialog. */
1474 window_destroy(GTK_WIDGET(parent_w));
1476 if (must_redissect) {
1477 /* Redissect all the packets, and re-evaluate the display filter. */
1478 redissect_packets();
1479 redissect_all_packet_windows();
1485 prefs_main_apply_cb(GtkWidget *apply_bt _U_, gpointer parent_w)
1487 gboolean must_redissect = FALSE;
1489 if (!prefs_main_fetch_all((GtkWidget *)parent_w, &must_redissect))
1490 return; /* Errors in some preference setting - already reported */
1492 /* if we don't have a Save button, just save the settings now */
1493 if (!prefs.gui_use_pref_save) {
1494 prefs_main_save(parent_w);
1495 prefs_copy(); /* save prefs for reverting if Cancel */
1498 prefs_main_apply_all((GtkWidget *)parent_w, must_redissect);
1500 /* Fill in capture options with values from the preferences */
1501 prefs_to_capture_opts();
1504 prefs_airpcap_update();
1507 if (must_redissect) {
1508 /* Redissect all the packets, and re-evaluate the display filter. */
1509 redissect_packets();
1510 redissect_all_packet_windows();
1515 prefs_main_save_cb(GtkWidget *save_bt _U_, gpointer parent_w)
1517 gboolean must_redissect = FALSE;
1519 if (!prefs_main_fetch_all((GtkWidget *)parent_w, &must_redissect))
1520 return; /* Errors in some preference setting - already reported */
1522 prefs_main_save(parent_w);
1523 prefs_copy(); /* save prefs for reverting if Cancel */
1525 /* Now apply those preferences.
1526 XXX - should we do this? The user didn't click "OK" or "Apply".
1529 1) by saving the preferences they presumably indicate that they
1532 2) the next time they fire Wireshark up, those preferences will
1535 3) we'd have to buffer "must_redissect" so that if they do
1536 "Apply" after this, we know we have to redissect;
1538 4) we did apply the protocol preferences, at least, in the past. */
1539 prefs_main_apply_all((GtkWidget *)parent_w, must_redissect);
1541 /* Fill in capture options with values from the preferences */
1542 prefs_to_capture_opts();
1544 if (must_redissect) {
1545 /* Redissect all the packets, and re-evaluate the display filter. */
1546 redissect_packets();
1547 redissect_all_packet_windows();
1552 module_prefs_revert(module_t *module, gpointer user_data)
1554 gboolean *must_redissect_p = (gboolean *)user_data;
1556 /* Ignore any preferences with their own interface */
1557 if (!module->use_gui) {
1561 /* For all preferences in this module, revert its value to the value
1562 it had when we popped up the Preferences dialog. Find out whether
1563 this changes any of them. */
1564 module->prefs_changed = FALSE; /* assume none of them changed */
1565 prefs_pref_foreach(module, pref_unstash, &module->prefs_changed);
1567 /* If any of them changed, indicate that we must redissect and refilter
1568 the current capture (if we have one), as the preference change
1569 could cause packets to be dissected differently. */
1570 if (module->prefs_changed)
1571 *must_redissect_p = TRUE;
1572 return 0; /* keep processing modules */
1575 /* cancel button pressed, revert prefs to saved and exit dialog */
1577 prefs_main_cancel_cb(GtkWidget *cancel_bt _U_, gpointer parent_w)
1579 gboolean must_redissect = FALSE;
1581 /* Free up the current preferences and copy the saved preferences to the
1582 current preferences. */
1583 cfile.columns_changed = FALSE; /* [XXX: "columns_changed" should treally be stored in prefs struct ??] */
1585 /* Now revert the registered preferences. */
1586 prefs_modules_foreach(module_prefs_revert, &must_redissect);
1588 /* Now apply the reverted-to preferences. */
1589 prefs_main_apply_all((GtkWidget *)parent_w, must_redissect);
1591 window_destroy(GTK_WIDGET(parent_w));
1593 if (must_redissect) {
1594 /* Redissect all the packets, and re-evaluate the display filter. */
1595 redissect_packets();
1596 redissect_all_packet_windows();
1600 /* Treat this as a cancel, by calling "prefs_main_cancel_cb()" */
1602 prefs_main_delete_event_cb(GtkWidget *prefs_w_lcl, GdkEvent *event _U_,
1603 gpointer user_data _U_)
1605 prefs_main_cancel_cb(NULL, prefs_w_lcl);
1610 /* dialog *is* already destroyed, clean up memory and such */
1612 prefs_main_destroy_cb(GtkWidget *win _U_, gpointer parent_w)
1614 prefs_main_destroy_all((GtkWidget *)parent_w);
1616 /* Note that we no longer have a "Preferences" dialog box. */
1620 struct properties_data {
1626 module_search_properties(module_t *module, gpointer user_data)
1628 struct properties_data *p = (struct properties_data *)user_data;
1630 if (!module->use_gui) {
1631 /* This module uses its own GUI interface, so its not a part
1637 /* If this module has the specified title, remember it. */
1638 if (strcmp(module->title, p->title) == 0) {
1640 return 1; /* stops the search */
1643 if (prefs_module_has_submodules(module))
1644 return prefs_modules_foreach_submodules(module, module_search_properties, p);
1650 tree_expand_row(GtkTreeModel *model, GtkTreeView *tree_view, GtkTreeIter *iter)
1655 /* expand the parent first */
1656 if (gtk_tree_model_iter_parent(model, &parent, iter))
1657 tree_expand_row(model, tree_view, &parent);
1659 path = gtk_tree_model_get_path(model, iter);
1660 gtk_tree_view_expand_row(tree_view, path, FALSE);
1661 /*expand_tree(tree_view, &parent, NULL, NULL);*/
1663 gtk_tree_path_free(path);
1666 /* select a node in the tree view */
1667 /* XXX - this is almost 100% copied from byte_view_select() in proto_draw.c,
1668 * find a way to combine both to have a generic function for this */
1670 tree_select_node(GtkWidget *tree, prefs_tree_iter *iter)
1672 GtkTreeIter local_iter = *iter;
1673 GtkTreeView *tree_view = GTK_TREE_VIEW(tree);
1674 GtkTreeModel *model;
1675 GtkTreePath *first_path;
1677 model = gtk_tree_view_get_model(tree_view);
1679 /* Expand our field's row */
1680 first_path = gtk_tree_model_get_path(model, &local_iter);
1682 /* expand from the top down */
1683 tree_expand_row(model, tree_view, &local_iter);
1685 /* select our field's row */
1686 gtk_tree_selection_select_path(gtk_tree_view_get_selection(tree_view),
1689 /* And position the window so the selection is visible.
1690 * Position the selection in the middle of the viewable
1692 gtk_tree_view_scroll_to_cell(tree_view, first_path, NULL, TRUE, 0.5f, 0.0f);
1694 gtk_tree_path_free(first_path);
1698 /* search the corresponding protocol page of the currently selected field */
1700 properties_cb(GtkWidget *w, gpointer dummy)
1702 header_field_info *hfinfo;
1703 const gchar *title = NULL;
1704 struct properties_data p;
1708 module_t *page_module;
1710 if (cfile.finfo_selected == NULL) {
1711 const gchar *abbrev;
1713 /* There is no field selected, try use on top protocol */
1714 if (cfile.edt && cfile.edt->tree) {
1719 ga = proto_all_finfos(cfile.edt->tree);
1721 for (i = ga->len - 1; i > 0 ; i -= 1) {
1723 v = (field_info *)g_ptr_array_index (ga, i);
1726 if (!g_str_has_prefix(hfinfo->abbrev, "text") &&
1727 !g_str_has_prefix(hfinfo->abbrev, "expert") &&
1728 !g_str_has_prefix(hfinfo->abbrev, "malformed")) {
1729 if (hfinfo->parent == -1) {
1730 abbrev = hfinfo->abbrev;
1732 abbrev = proto_registrar_get_abbrev(hfinfo->parent);
1734 title = prefs_get_title_by_name(abbrev);
1740 /* Find the title for the protocol for the selected field. */
1741 hfinfo = cfile.finfo_selected->hfinfo;
1742 if (hfinfo->parent == -1)
1743 title = prefs_get_title_by_name(hfinfo->abbrev);
1745 title = prefs_get_title_by_name(proto_registrar_get_abbrev(hfinfo->parent));
1749 return; /* Couldn't find it. XXX - just crash? "Can't happen"? */
1751 /* Find the module for that protocol by searching for one with that title.
1752 XXX - should we just associate protocols with modules directly? */
1755 prefs_modules_foreach_submodules(protocols_module, module_search_properties,
1757 if (p.module == NULL) {
1758 /* We didn't find it - that protocol probably has no preferences. */
1762 /* Create a preferences window, or pop up an existing one. */
1763 if (prefs_w != NULL) {
1764 reactivate_window(prefs_w);
1769 /* Search all the pages in that window for the one with the specified
1772 (sw = gtk_notebook_get_nth_page((GtkNotebook *)g_object_get_data(G_OBJECT(prefs_w), E_PREFSW_NOTEBOOK_KEY), page_num)) != NULL;
1774 /* Get the frame from the scrollable window */
1775 frame = (GtkWidget *)g_object_get_data(G_OBJECT(sw), E_PAGESW_FRAME_KEY);
1776 /* Get the module for this page (non-protocol prefs don't have one). */
1778 page_module = (module_t *)g_object_get_data(G_OBJECT(frame), E_PAGE_MODULE_KEY);
1779 if (page_module != NULL) {
1780 if (page_module == p.module) {
1782 (GtkWidget *)g_object_get_data(G_OBJECT(prefs_w), E_PREFSW_TREE_KEY),
1783 (GtkTreeIter *)g_object_get_data(G_OBJECT(frame), E_PAGE_ITER_KEY));
1791 /* Prefs tree selection callback. The node data has been loaded with
1792 the proper notebook page to load. */
1794 prefs_tree_select_cb(GtkTreeSelection *sel, gpointer dummy _U_)
1797 GtkTreeModel *model;
1800 if (gtk_tree_selection_get_selected(sel, &model, &iter))
1802 gtk_tree_model_get(model, &iter, 1, &page, -1);
1804 gtk_notebook_set_current_page((GtkNotebook *)g_object_get_data(G_OBJECT(prefs_w), E_PREFSW_NOTEBOOK_KEY), page);
1816 * indent-tabs-mode: nil
1819 * ex: set shiftwidth=2 tabstop=8 expandtab:
1820 * :indentSize=2:tabSize=8:noTabs=true: