2 * Routines for handling preferences
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
33 #include <epan/filesystem.h>
34 #include <epan/packet.h>
35 #include <epan/prefs.h>
36 #include <epan/strutil.h>
37 #include <epan/prefs-int.h>
41 #include "../simple_dialog.h"
44 #include "gtk/prefs_column.h"
45 #include "gtk/prefs_dlg.h"
46 #include "gtk/prefs_print.h"
47 #include "gtk/prefs_stream.h"
48 #include "gtk/prefs_gui.h"
49 #include "gtk/prefs_layout.h"
50 #include "gtk/prefs_capture.h"
51 #include "gtk/prefs_nameres.h"
52 #include "gtk/prefs_taps.h"
53 #include "gtk/prefs_protocols.h"
54 #include "gtk/gui_utils.h"
55 #include "gtk/dlg_utils.h"
56 #include "gtk/stock_icons.h"
57 #include "gtk/help_dlg.h"
59 #include "gtk/uat_gui.h"
60 #ifndef NEW_PACKET_LIST
61 #include "gtk/main_packet_list.h"
67 #include "capture-wpcap.h"
71 #include "airpcap_loader.h"
72 #include "airpcap_gui_utils.h"
77 static void prefs_main_ok_cb(GtkWidget *, gpointer);
78 static void prefs_main_apply_cb(GtkWidget *, gpointer);
79 static void prefs_main_save_cb(GtkWidget *, gpointer);
80 static void prefs_main_cancel_cb(GtkWidget *, gpointer);
81 static gboolean prefs_main_delete_event_cb(GtkWidget *, GdkEvent *, gpointer);
82 static void prefs_main_destroy_cb(GtkWidget *, gpointer);
83 static void prefs_tree_select_cb(GtkTreeSelection *, gpointer);
86 #define E_PREFSW_SCROLLW_KEY "prefsw_scrollw"
87 #define E_PREFSW_TREE_KEY "prefsw_tree"
88 #define E_PREFSW_NOTEBOOK_KEY "prefsw_notebook"
89 #define E_PREFSW_SAVE_BT_KEY "prefsw_save_bt"
90 #define E_PAGE_ITER_KEY "page_iter"
91 #define E_PAGE_MODULE_KEY "page_module"
92 #define E_PAGESW_FRAME_KEY "pagesw_frame"
94 #define E_GUI_PAGE_KEY "gui_options_page"
95 #define E_GUI_LAYOUT_PAGE_KEY "gui_layout_page"
96 #define E_GUI_COLUMN_PAGE_KEY "gui_column_options_page"
97 #define E_GUI_FONT_PAGE_KEY "gui_font_options_page"
98 #define E_GUI_COLORS_PAGE_KEY "gui_colors_options_page"
99 #define E_CAPTURE_PAGE_KEY "capture_options_page"
100 #define E_PRINT_PAGE_KEY "printer_options_page"
101 #define E_NAMERES_PAGE_KEY "nameres_options_page"
102 #define E_TAPS_PAGE_KEY "taps_options_page"
103 #define E_PROTOCOLS_PAGE_KEY "protocols_options_page"
106 * Keep a static pointer to the current "Preferences" window, if any, so that
107 * if somebody tries to do "Edit:Preferences" while there's already a
108 * "Preferences" window up, we just pop up the existing one, rather than
109 * creating a new one.
111 static GtkWidget *prefs_w;
114 * Save the value of the preferences as of when the preferences dialog
115 * box was first popped up, so we can revert to those values if the
116 * user selects "Cancel".
118 static e_prefs saved_prefs;
125 GtkTooltips *tooltips;
127 gboolean is_protocol;
130 static gint protocols_page = 0;
133 pref_exists(pref_t *pref _U_, gpointer user_data _U_)
138 /* show a single preference on the GtkTable of a preference page */
140 pref_show(pref_t *pref, gpointer user_data)
142 GtkWidget *main_tb = user_data;
148 /* Give this preference a label which is its title, followed by a colon,
149 and left-align it. */
151 label_len = strlen(title) + 2;
152 label_string = g_malloc(label_len);
153 g_strlcpy(label_string, title, label_len);
156 * Sometimes we don't want to append a ':' after a static text string...
157 * If it is needed, we will specify it in the string itself.
159 if(pref->type != PREF_STATIC_TEXT)
160 g_strlcat(label_string, ":", label_len);
162 /* Save the current value of the preference, so that we can revert it if
163 the user does "Apply" and then "Cancel", and create the control for
164 editing the preference. */
165 switch (pref->type) {
168 pref->saved_val.uint = *pref->varp.uint;
170 /* XXX - there are no uint spinbuttons, so we can't use a spinbutton.
171 Even more annoyingly, even if there were, GLib doesn't define
172 G_MAXUINT - but I think ANSI C may define UINT_MAX, so we could
174 switch (pref->info.base) {
177 g_snprintf(uint_str, sizeof(uint_str), "%u", pref->saved_val.uint);
181 g_snprintf(uint_str, sizeof(uint_str), "%o", pref->saved_val.uint);
185 g_snprintf(uint_str, sizeof(uint_str), "%x", pref->saved_val.uint);
188 pref->control = create_preference_entry(main_tb, pref->ordinal,
189 label_string, pref->description,
194 pref->saved_val.boolval = *pref->varp.boolp;
195 pref->control = create_preference_check_button(main_tb, pref->ordinal,
196 label_string, pref->description,
197 pref->saved_val.boolval);
201 pref->saved_val.enumval = *pref->varp.enump;
202 if (pref->info.enum_info.radio_buttons) {
203 /* Show it as radio buttons. */
204 pref->control = create_preference_radio_buttons(main_tb, pref->ordinal,
205 label_string, pref->description,
206 pref->info.enum_info.enumvals,
207 pref->saved_val.enumval);
209 /* Show it as an option menu. */
210 pref->control = create_preference_option_menu(main_tb, pref->ordinal,
211 label_string, pref->description,
212 pref->info.enum_info.enumvals,
213 pref->saved_val.enumval);
218 g_free(pref->saved_val.string);
219 pref->saved_val.string = g_strdup(*pref->varp.string);
220 pref->control = create_preference_entry(main_tb, pref->ordinal,
221 label_string, pref->description,
222 pref->saved_val.string);
229 g_free(pref->saved_val.range);
230 pref->saved_val.range = range_copy(*pref->varp.range);
231 range_str_p = range_convert_range(*pref->varp.range);
232 pref->control = create_preference_entry(main_tb, pref->ordinal,
233 label_string, pref->description,
238 case PREF_STATIC_TEXT:
240 pref->control = create_preference_static_text(main_tb, pref->ordinal,
241 label_string, pref->description);
247 pref->control = create_preference_uat(main_tb, pref->ordinal,
248 label_string, pref->description,
254 g_assert_not_reached();
257 g_free(label_string);
262 #define MAX_TREE_NODE_NAME_LEN 64
263 /* show prefs page for each registered module (protocol) */
265 module_prefs_show(module_t *module, gpointer user_data)
267 struct ct_struct *cts = user_data;
268 struct ct_struct child_cts;
269 GtkWidget *main_vb, *main_tb, *frame, *main_sw;
270 gchar label_str[MAX_TREE_NODE_NAME_LEN];
275 * Is this module a subtree, with modules underneath it?
277 if (!prefs_module_has_submodules(module)) {
280 * Does it have any preferences (other than possibly obsolete ones)?
282 if (prefs_pref_foreach(module, pref_exists, NULL) == 0) {
284 * No. Don't put the module into the preferences window.
285 * XXX - we should do the same for subtrees; if a subtree has
286 * nothing under it that will be displayed, don't put it into
294 * Add this module to the tree.
296 g_strlcpy(label_str, module->title, MAX_TREE_NODE_NAME_LEN);
297 model = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(cts->tree)));
298 if (prefs_module_has_submodules(module) && !cts->iter.stamp)
299 gtk_tree_store_append(model, &iter, NULL);
301 gtk_tree_store_append(model, &iter, &cts->iter);
306 if (prefs_module_has_submodules(module)) {
311 gtk_tree_store_set(model, &iter, 0, label_str, 1, -1, -1);
314 * Walk the subtree and attach stuff to it.
317 child_cts.iter = iter;
318 if (module == protocols_module)
319 child_cts.is_protocol = TRUE;
320 prefs_modules_foreach_submodules(module, module_prefs_show, &child_cts);
322 /* keep the page count right */
323 cts->page = child_cts.page;
328 * Has preferences. Create a notebook page for it.
331 /* Scrolled window */
332 main_sw = gtk_scrolled_window_new(NULL, NULL);
333 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(main_sw), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
336 frame = gtk_frame_new(module->description);
337 gtk_container_set_border_width(GTK_CONTAINER(frame), 5);
338 gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(main_sw), frame);
339 g_object_set_data(G_OBJECT(main_sw), E_PAGESW_FRAME_KEY, frame);
341 /* Main vertical box */
342 main_vb = gtk_vbox_new(FALSE, 5);
343 gtk_container_set_border_width(GTK_CONTAINER(main_vb), 5);
344 gtk_container_add(GTK_CONTAINER(frame), main_vb);
347 main_tb = gtk_table_new(module->numprefs, 2, FALSE);
348 gtk_box_pack_start(GTK_BOX(main_vb), main_tb, FALSE, FALSE, 0);
349 gtk_table_set_row_spacings(GTK_TABLE(main_tb), 10);
350 gtk_table_set_col_spacings(GTK_TABLE(main_tb), 15);
351 g_object_set_data(G_OBJECT(main_tb), E_TOOLTIPS_KEY, cts->tooltips);
353 /* Add items for each of the preferences */
354 prefs_pref_foreach(module, pref_show, main_tb);
356 /* Associate this module with the page's frame. */
357 g_object_set_data(G_OBJECT(frame), E_PAGE_MODULE_KEY, module);
359 /* Add the page to the notebook */
360 gtk_notebook_append_page(GTK_NOTEBOOK(cts->notebook), main_sw, NULL);
362 /* Attach the page to the tree item */
363 gtk_tree_store_set(model, &iter, 0, label_str, 1, cts->page, -1);
364 g_object_set_data(G_OBJECT(frame), E_PAGE_ITER_KEY, gtk_tree_iter_copy(&iter));
368 /* Show 'em what we got */
369 gtk_widget_show_all(main_sw);
371 /* show the protocols page */
373 gtk_tree_store_set(model, &iter, 0, label_str, 1, protocols_page, -1);
381 #define prefs_tree_iter GtkTreeIter
383 /* add a page to the tree */
384 static prefs_tree_iter
385 prefs_tree_page_add(const gchar *title, gint page_nr,
386 gpointer store, prefs_tree_iter *parent_iter)
388 prefs_tree_iter iter;
390 gtk_tree_store_append(store, &iter, parent_iter);
391 gtk_tree_store_set(store, &iter, 0, title, 1, page_nr, -1);
395 /* add a page to the notebook */
397 prefs_nb_page_add(GtkWidget *notebook, const gchar *title, GtkWidget *page, const char *page_key)
401 frame = gtk_frame_new(title);
402 gtk_widget_show(frame);
404 gtk_container_add(GTK_CONTAINER(frame), page);
405 g_object_set_data(G_OBJECT(prefs_w), page_key, page);
407 gtk_notebook_append_page (GTK_NOTEBOOK(notebook), frame, NULL);
413 /* show the dialog */
415 prefs_cb(GtkWidget *w, gpointer dummy)
417 prefs_page_cb (w, dummy, PREFS_PAGE_USER_INTERFACE);
421 prefs_page_cb(GtkWidget *w _U_, gpointer dummy _U_, PREFS_PAGE_E prefs_page)
423 GtkWidget *top_hb, *bbox, *prefs_nb, *ct_sb,
424 *ok_bt, *apply_bt, *save_bt, *cancel_bt, *help_bt;
425 GtkWidget *gui_font_pg;
426 gchar label_str[MAX_TREE_NODE_NAME_LEN];
427 struct ct_struct cts;
429 GtkTreeSelection *selection;
430 GtkCellRenderer *renderer;
431 GtkTreeViewColumn *column;
433 prefs_tree_iter gui_iter, layout_iter, columns_iter;
434 gint layout_page, columns_page;
437 if (prefs_w != NULL) {
438 /* There's already a "Preferences" dialog box; reactivate it. */
439 reactivate_window(prefs_w);
443 /* Save the current preferences, so we can revert to those values
444 if the user presses "Cancel". */
445 copy_prefs(&saved_prefs, &prefs);
447 prefs_w = dlg_conf_window_new("Wireshark: Preferences");
450 * Unfortunately, we can't arrange that a GtkTable widget wrap an event box
451 * around a table row, so the spacing between the preference item's label
452 * and its control widgets is inactive and the tooltip doesn't pop up when
453 * the mouse is over it.
455 cts.tooltips = gtk_tooltips_new();
457 /* Container for each row of widgets */
458 cts.main_vb = gtk_vbox_new(FALSE, 5);
459 gtk_container_set_border_width(GTK_CONTAINER(cts.main_vb), 5);
460 gtk_container_add(GTK_CONTAINER(prefs_w), cts.main_vb);
461 gtk_widget_show(cts.main_vb);
463 /* Top row: Preferences tree and notebook */
464 top_hb = gtk_hbox_new(FALSE, 10);
465 gtk_container_add(GTK_CONTAINER(cts.main_vb), top_hb);
466 gtk_widget_show(top_hb);
468 /* scrolled window on the left for the categories tree */
469 ct_sb = scrolled_window_new(NULL, NULL);
470 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(ct_sb),
472 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(ct_sb),
473 GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
474 gtk_container_add(GTK_CONTAINER(top_hb), ct_sb);
475 gtk_widget_show(ct_sb);
476 g_object_set_data(G_OBJECT(prefs_w), E_PREFSW_SCROLLW_KEY, ct_sb);
478 /* categories tree */
479 store = gtk_tree_store_new(2, G_TYPE_STRING, G_TYPE_INT);
480 cts.tree = tree_view_new(GTK_TREE_MODEL(store));
481 cts.iter.stamp = 0; /* mark this as the toplevel */
482 g_object_set_data(G_OBJECT(prefs_w), E_PREFSW_TREE_KEY, cts.tree);
483 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(cts.tree), FALSE);
484 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(cts.tree));
485 gtk_tree_selection_set_mode(selection, GTK_SELECTION_SINGLE);
486 renderer = gtk_cell_renderer_text_new();
487 col_offset = gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(cts.tree),
488 -1, "Name", renderer,
490 column = gtk_tree_view_get_column(GTK_TREE_VIEW(cts.tree),
492 gtk_tree_view_column_set_sizing(GTK_TREE_VIEW_COLUMN(column),
493 GTK_TREE_VIEW_COLUMN_AUTOSIZE);
494 g_signal_connect(selection, "changed", G_CALLBACK(prefs_tree_select_cb), NULL);
495 gtk_container_add(GTK_CONTAINER(ct_sb), cts.tree);
496 gtk_widget_show(cts.tree);
498 /* A notebook widget without tabs is used to flip between prefs */
499 prefs_nb = gtk_notebook_new();
500 g_object_set_data(G_OBJECT(prefs_w), E_PREFSW_NOTEBOOK_KEY, prefs_nb);
501 gtk_notebook_set_show_tabs(GTK_NOTEBOOK(prefs_nb), FALSE);
502 gtk_notebook_set_show_border(GTK_NOTEBOOK(prefs_nb), FALSE);
503 gtk_container_add(GTK_CONTAINER(top_hb), prefs_nb);
504 gtk_widget_show(prefs_nb);
508 /* Preferences common for all protocols */
509 g_strlcpy(label_str, "Protocols", MAX_TREE_NODE_NAME_LEN);
510 prefs_nb_page_add(prefs_nb, label_str, protocols_prefs_show(), E_PROTOCOLS_PAGE_KEY);
511 protocols_page = cts.page++;
514 g_strlcpy(label_str, "User Interface", MAX_TREE_NODE_NAME_LEN);
515 prefs_nb_page_add(prefs_nb, label_str, gui_prefs_show(), E_GUI_PAGE_KEY);
516 gui_iter = prefs_tree_page_add(label_str, cts.page, store, NULL);
519 /* GUI layout prefs */
520 g_strlcpy(label_str, "Layout", MAX_TREE_NODE_NAME_LEN);
521 prefs_nb_page_add(prefs_nb, label_str, layout_prefs_show(), E_GUI_LAYOUT_PAGE_KEY);
522 layout_iter = prefs_tree_page_add(label_str, cts.page, store, &gui_iter);
523 layout_page = cts.page++;
525 /* GUI Column prefs */
526 g_strlcpy(label_str, "Columns", MAX_TREE_NODE_NAME_LEN);
527 prefs_nb_page_add(prefs_nb, label_str, column_prefs_show(prefs_w), E_GUI_COLUMN_PAGE_KEY);
528 columns_iter = prefs_tree_page_add(label_str, cts.page, store, &gui_iter);
529 columns_page = cts.page++;
532 g_strlcpy(label_str, "Font", MAX_TREE_NODE_NAME_LEN);
533 gui_font_pg = gui_font_prefs_show();
534 prefs_nb_page_add(prefs_nb, label_str, gui_font_pg, E_GUI_FONT_PAGE_KEY);
535 prefs_tree_page_add(label_str, cts.page, store, &gui_iter);
538 gtk_container_set_border_width( GTK_CONTAINER(gui_font_pg), 5 );
540 /* IMPORTANT: the following gtk_font_selection_set_font_name() function will
541 only work if the widget and it's corresponding window is already shown
542 (so don't put the following into gui_font_prefs_show()) !!! */
544 /* We set the current font now, because setting it appears not to work
545 when run before appending the frame to the notebook. */
547 gtk_font_selection_set_font_name(
548 GTK_FONT_SELECTION(gui_font_pg), prefs.gui_font_name);
550 /* GUI Colors prefs */
551 g_strlcpy(label_str, "Colors", MAX_TREE_NODE_NAME_LEN);
552 prefs_nb_page_add(prefs_nb, label_str, stream_prefs_show(), E_GUI_COLORS_PAGE_KEY);
553 prefs_tree_page_add(label_str, cts.page, store, &gui_iter);
556 /* select the main GUI page as the default page and expand it's children */
557 gtk_tree_selection_select_iter(selection, &gui_iter);
558 /* (expand will only take effect, when at least one child exists) */
559 gtk_tree_view_expand_all(GTK_TREE_VIEW(cts.tree));
563 /* Is WPcap loaded? */
567 g_strlcpy(label_str, "Capture", MAX_TREE_NODE_NAME_LEN);
568 prefs_nb_page_add(prefs_nb, label_str, capture_prefs_show(), E_CAPTURE_PAGE_KEY);
569 prefs_tree_page_add(label_str, cts.page, store, NULL);
574 #endif /* HAVE_LIBPCAP */
577 g_strlcpy(label_str, "Printing", MAX_TREE_NODE_NAME_LEN);
578 prefs_nb_page_add(prefs_nb, label_str, printer_prefs_show(), E_PRINT_PAGE_KEY);
579 prefs_tree_page_add(label_str, cts.page, store, NULL);
582 /* Name resolution prefs */
583 g_strlcpy(label_str, "Name Resolution", MAX_TREE_NODE_NAME_LEN);
584 prefs_nb_page_add(prefs_nb, label_str, nameres_prefs_show(), E_NAMERES_PAGE_KEY);
585 prefs_tree_page_add(label_str, cts.page, store, NULL);
588 /* TAPS player prefs */
589 g_strlcpy(label_str, "Statistics", MAX_TREE_NODE_NAME_LEN);
590 prefs_nb_page_add(prefs_nb, label_str, stats_prefs_show(), E_TAPS_PAGE_KEY);
591 prefs_tree_page_add(label_str, cts.page, store, NULL);
594 /* Registered prefs */
595 cts.notebook = prefs_nb;
596 cts.is_protocol = FALSE;
597 prefs_modules_foreach_submodules(NULL, module_prefs_show, &cts);
599 /* Button row: OK and alike buttons */
600 bbox = dlg_button_row_new(GTK_STOCK_HELP, GTK_STOCK_OK, GTK_STOCK_APPLY, GTK_STOCK_SAVE, GTK_STOCK_CANCEL, NULL);
601 gtk_box_pack_start(GTK_BOX(cts.main_vb), bbox, FALSE, FALSE, 0);
602 gtk_widget_show(bbox);
604 ok_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_OK);
605 g_signal_connect(ok_bt, "clicked", G_CALLBACK(prefs_main_ok_cb), prefs_w);
607 apply_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_APPLY);
608 g_signal_connect(apply_bt, "clicked", G_CALLBACK(prefs_main_apply_cb), prefs_w);
610 save_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_SAVE);
611 g_signal_connect(save_bt, "clicked", G_CALLBACK(prefs_main_save_cb), prefs_w);
612 g_object_set_data(G_OBJECT(prefs_w), E_PREFSW_SAVE_BT_KEY, save_bt);
614 cancel_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_CANCEL);
615 g_signal_connect(cancel_bt, "clicked", G_CALLBACK(prefs_main_cancel_cb), prefs_w);
616 window_set_cancel_button(prefs_w, cancel_bt, NULL);
618 gtk_widget_grab_default(ok_bt);
620 help_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_HELP);
621 g_signal_connect(help_bt, "clicked", G_CALLBACK(topic_cb), (gpointer)HELP_PREFERENCES_DIALOG);
623 g_signal_connect(prefs_w, "delete_event", G_CALLBACK(prefs_main_delete_event_cb), NULL);
624 g_signal_connect(prefs_w, "destroy", G_CALLBACK(prefs_main_destroy_cb), prefs_w);
626 gtk_widget_show(prefs_w);
628 /* hide the Save button if the user uses implicit save */
629 if(!prefs.gui_use_pref_save) {
630 gtk_widget_hide(save_bt);
633 window_present(prefs_w);
635 switch (prefs_page) {
636 case PREFS_PAGE_LAYOUT:
637 gtk_tree_selection_select_iter(selection, &layout_iter);
638 gtk_notebook_set_current_page(g_object_get_data(G_OBJECT(prefs_w), E_PREFSW_NOTEBOOK_KEY), layout_page);
640 case PREFS_PAGE_COLUMNS:
641 gtk_tree_selection_select_iter(selection, &columns_iter);
642 gtk_notebook_set_current_page(g_object_get_data(G_OBJECT(prefs_w), E_PREFSW_NOTEBOOK_KEY), columns_page);
645 /* Not implemented yet */
649 g_object_unref(G_OBJECT(store));
653 set_option_label(GtkWidget *main_tb, int table_position,
654 const gchar *label_text, const gchar *tooltip_text, GtkTooltips *tooltips)
657 GtkWidget *event_box;
659 label = gtk_label_new(label_text);
660 gtk_misc_set_alignment(GTK_MISC(label), 1.0f, 0.5f);
661 gtk_widget_show(label);
663 event_box = gtk_event_box_new();
664 gtk_event_box_set_visible_window (GTK_EVENT_BOX(event_box), FALSE);
665 gtk_table_attach_defaults(GTK_TABLE(main_tb), event_box, 0, 1,
666 table_position, table_position + 1);
667 if (tooltip_text != NULL && tooltips != NULL)
668 gtk_tooltips_set_tip(tooltips, event_box, tooltip_text, NULL);
669 gtk_container_add(GTK_CONTAINER(event_box), label);
670 gtk_widget_show(event_box);
674 create_preference_check_button(GtkWidget *main_tb, int table_position,
675 const gchar *label_text, const gchar *tooltip_text, gboolean active)
677 GtkTooltips *tooltips;
678 GtkWidget *check_box;
680 tooltips = g_object_get_data(G_OBJECT(main_tb), E_TOOLTIPS_KEY);
682 set_option_label(main_tb, table_position, label_text, tooltip_text,
685 check_box = gtk_check_button_new();
686 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check_box), active);
687 gtk_table_attach_defaults(GTK_TABLE(main_tb), check_box, 1, 2,
688 table_position, table_position + 1);
689 if (tooltip_text != NULL && tooltips != NULL)
690 gtk_tooltips_set_tip(tooltips, check_box, tooltip_text, NULL);
696 create_preference_radio_buttons(GtkWidget *main_tb, int table_position,
697 const gchar *label_text, const gchar *tooltip_text,
698 const enum_val_t *enumvals, gint current_val)
700 GtkTooltips *tooltips;
701 GtkWidget *radio_button_hbox, *button = NULL;
704 const enum_val_t *enum_valp;
705 GtkWidget *event_box;
707 tooltips = g_object_get_data(G_OBJECT(main_tb), E_TOOLTIPS_KEY);
709 set_option_label(main_tb, table_position, label_text, tooltip_text,
712 radio_button_hbox = gtk_hbox_new(FALSE, 0);
714 for (enum_valp = enumvals, idx = 0; enum_valp->name != NULL;
715 enum_valp++, idx++) {
716 button = gtk_radio_button_new_with_label(rb_group,
717 enum_valp->description);
718 gtk_widget_show(button);
719 rb_group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(button));
720 gtk_box_pack_start(GTK_BOX(radio_button_hbox), button, FALSE,
722 if (enum_valp->value == current_val) {
723 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button),
727 gtk_widget_show(radio_button_hbox);
729 event_box = gtk_event_box_new();
730 gtk_event_box_set_visible_window (GTK_EVENT_BOX(event_box), FALSE);
731 gtk_container_add(GTK_CONTAINER(event_box), radio_button_hbox);
732 gtk_table_attach_defaults(GTK_TABLE(main_tb), event_box, 1, 2,
733 table_position, table_position+1);
734 if (tooltip_text != NULL && tooltips != NULL)
735 gtk_tooltips_set_tip(tooltips, event_box, tooltip_text, NULL);
736 gtk_widget_show(event_box);
739 * It doesn't matter which of the buttons we return - we fetch
740 * the value by looking at the entire radio button group to
741 * which it belongs, and we can get that from any button.
747 label_to_enum_val(GtkWidget *label, const enum_val_t *enumvals)
749 const gchar *label_string;
752 /* Get the label's text, and translate it to a value.
753 We match only the descriptions, as those are what appear in
754 the option menu items or as labels for radio buttons.
755 We fail if we don't find a match, as that "can't happen". */
756 label_string = gtk_label_get_text(GTK_LABEL(label));
758 for (i = 0; enumvals[i].name != NULL; i++) {
759 if (g_ascii_strcasecmp(label_string, enumvals[i].description) == 0) {
760 return enumvals[i].value;
763 g_assert_not_reached();
768 fetch_preference_radio_buttons_val(GtkWidget *button,
769 const enum_val_t *enumvals)
775 * Go through the list of of radio buttons in the button's group,
776 * and find the first one that's active.
778 rb_group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(button));
780 for (rb_entry = rb_group; rb_entry != NULL;
781 rb_entry = g_slist_next(rb_entry)) {
782 button = rb_entry->data;
783 if (GTK_TOGGLE_BUTTON(button)->active)
787 /* OK, now return the value corresponding to that button's label. */
788 return label_to_enum_val(GTK_BIN(button)->child, enumvals);
792 create_preference_option_menu(GtkWidget *main_tb, int table_position,
793 const gchar *label_text, const gchar *tooltip_text,
794 const enum_val_t *enumvals, gint current_val)
796 GtkTooltips *tooltips;
797 GtkWidget *menu_box, *combo_box;
799 const enum_val_t *enum_valp;
800 GtkWidget *event_box;
802 tooltips = g_object_get_data(G_OBJECT(main_tb), E_TOOLTIPS_KEY);
804 set_option_label(main_tb, table_position, label_text, tooltip_text,
807 /* Create a menu from the enumvals */
808 combo_box = gtk_combo_box_new_text ();
809 if (tooltip_text != NULL && tooltips != NULL)
810 gtk_tooltips_set_tip(tooltips, combo_box, tooltip_text, NULL);
812 for (enum_valp = enumvals, idx = 0; enum_valp->name != NULL;
813 enum_valp++, idx++) {
814 gtk_combo_box_append_text (GTK_COMBO_BOX (combo_box), enum_valp->description);
815 if (enum_valp->value == current_val)
818 /* Set the current value active */
819 gtk_combo_box_set_active(GTK_COMBO_BOX(combo_box), menu_idx);
822 * Put the combo box in an hbox, so that it's only as wide
823 * as the widest entry, rather than being as wide as the table
826 menu_box = gtk_hbox_new(FALSE, 0);
827 gtk_box_pack_start(GTK_BOX(menu_box), combo_box, FALSE, FALSE, 0);
829 event_box = gtk_event_box_new();
830 gtk_event_box_set_visible_window (GTK_EVENT_BOX(event_box), FALSE);
831 gtk_table_attach_defaults(GTK_TABLE(main_tb), event_box,
832 1, 2, table_position, table_position + 1);
833 if (tooltip_text != NULL && tooltips != NULL)
834 gtk_tooltips_set_tip(tooltips, event_box, tooltip_text, NULL);
835 gtk_container_add(GTK_CONTAINER(event_box), menu_box);
841 fetch_preference_option_menu_val(GtkWidget *combo_box, const enum_val_t *enumvals)
844 * OK, now return the value corresponding to the label for the
845 * currently active entry in the combo box.
849 i = gtk_combo_box_get_active (GTK_COMBO_BOX(combo_box));
851 return enumvals[i].value;
855 create_preference_entry(GtkWidget *main_tb, int table_position,
856 const gchar *label_text, const gchar *tooltip_text, char *value)
858 GtkTooltips *tooltips;
861 tooltips = g_object_get_data(G_OBJECT(main_tb), E_TOOLTIPS_KEY);
863 set_option_label(main_tb, table_position, label_text, tooltip_text,
866 entry = gtk_entry_new();
868 gtk_entry_set_text(GTK_ENTRY(entry), value);
869 gtk_table_attach_defaults(GTK_TABLE(main_tb), entry, 1, 2,
870 table_position, table_position + 1);
871 if (tooltip_text != NULL && tooltips != NULL)
872 gtk_tooltips_set_tip(tooltips, entry, tooltip_text, NULL);
873 gtk_widget_show(entry);
879 create_preference_static_text(GtkWidget *main_tb, int table_position,
880 const gchar *label_text, const gchar *tooltip_text)
882 GtkTooltips *tooltips;
885 tooltips = g_object_get_data(G_OBJECT(main_tb), E_TOOLTIPS_KEY);
887 if(label_text != NULL)
888 label = gtk_label_new(label_text);
890 label = gtk_label_new("");
891 gtk_table_attach_defaults(GTK_TABLE(main_tb), label, 0, 2,
892 table_position, table_position + 1);
893 if (tooltip_text != NULL && tooltips != NULL)
894 gtk_tooltips_set_tip(tooltips, label, tooltip_text, NULL);
895 gtk_widget_show(label);
901 create_preference_uat(GtkWidget *main_tb, int table_position,
902 const gchar *label_text, const gchar *tooltip_text, void* uat)
904 GtkTooltips *tooltips;
905 GtkWidget *button = NULL;
907 tooltips = g_object_get_data(G_OBJECT(main_tb), E_TOOLTIPS_KEY);
909 set_option_label(main_tb, table_position, label_text, tooltip_text,
912 button = gtk_button_new_from_stock(WIRESHARK_STOCK_EDIT);
914 g_signal_connect(button, "clicked", G_CALLBACK(uat_window_cb), uat);
916 gtk_table_attach_defaults(GTK_TABLE(main_tb), button, 1, 2,
917 table_position, table_position+1);
918 if (tooltip_text != NULL && tooltips != NULL)
919 gtk_tooltips_set_tip(tooltips, button, tooltip_text, NULL);
920 gtk_widget_show(button);
927 pref_check(pref_t *pref, gpointer user_data)
932 pref_t **badpref = user_data;
934 /* Fetch the value of the preference, and check whether it's valid. */
935 switch (pref->type) {
938 str_val = gtk_entry_get_text(GTK_ENTRY(pref->control));
939 uval = strtoul(str_val, &p, pref->info.base);
940 if (p == str_val || *p != '\0') {
942 return PREFS_SET_SYNTAX_ERR; /* number was bad */
947 /* Value can't be bad. */
951 /* Value can't be bad. */
955 /* Value can't be bad. */
959 str_val = gtk_entry_get_text(GTK_ENTRY(pref->control));
961 if (strlen(str_val) != 0) {
964 if (range_convert_str(&newrange, str_val, pref->info.max_value) != CVT_NO_ERROR) {
966 return PREFS_SET_SYNTAX_ERR; /* range was bad */
972 case PREF_STATIC_TEXT:
974 /* Value can't be bad. */
978 g_assert_not_reached();
985 module_prefs_check(module_t *module, gpointer user_data)
987 /* For all preferences in this module, fetch its value from this
988 module's notebook page and check whether it's valid. */
989 return prefs_pref_foreach(module, pref_check, user_data);
993 pref_fetch(pref_t *pref, gpointer user_data)
1000 gboolean *pref_changed_p = user_data;
1002 /* Fetch the value of the preference, and set the appropriate variable
1004 switch (pref->type) {
1007 str_val = gtk_entry_get_text(GTK_ENTRY(pref->control));
1008 uval = strtoul(str_val, &p, pref->info.base);
1010 if (p == value || *p != '\0')
1011 return PREFS_SET_SYNTAX_ERR; /* number was bad */
1013 if (*pref->varp.uint != uval) {
1014 *pref_changed_p = TRUE;
1015 *pref->varp.uint = uval;
1020 bval = GTK_TOGGLE_BUTTON(pref->control)->active;
1021 if (*pref->varp.boolp != bval) {
1022 *pref_changed_p = TRUE;
1023 *pref->varp.boolp = bval;
1028 if (pref->info.enum_info.radio_buttons) {
1029 enumval = fetch_preference_radio_buttons_val(pref->control,
1030 pref->info.enum_info.enumvals);
1032 enumval = fetch_preference_option_menu_val(pref->control,
1033 pref->info.enum_info.enumvals);
1036 if (*pref->varp.enump != enumval) {
1037 *pref_changed_p = TRUE;
1038 *pref->varp.enump = enumval;
1043 str_val = gtk_entry_get_text(GTK_ENTRY(pref->control));
1044 if (strcmp(*pref->varp.string, str_val) != 0) {
1045 *pref_changed_p = TRUE;
1046 g_free((void *)*pref->varp.string);
1047 *pref->varp.string = g_strdup(str_val);
1056 str_val = gtk_entry_get_text(GTK_ENTRY(pref->control));
1057 ret = range_convert_str(&newrange, str_val, pref->info.max_value);
1058 if (ret != CVT_NO_ERROR)
1060 return PREFS_SET_SYNTAX_ERR; /* range was bad */
1062 return 0; /* XXX - should fail */
1065 if (!ranges_are_equal(*pref->varp.range, newrange)) {
1066 *pref_changed_p = TRUE;
1067 g_free(*pref->varp.range);
1068 *pref->varp.range = newrange;
1075 case PREF_STATIC_TEXT:
1080 g_assert_not_reached();
1087 module_prefs_fetch(module_t *module, gpointer user_data)
1089 gboolean *must_redissect_p = user_data;
1091 /* For all preferences in this module, fetch its value from this
1092 module's notebook page. Find out whether any of them changed. */
1093 module->prefs_changed = FALSE; /* assume none of them changed */
1094 prefs_pref_foreach(module, pref_fetch, &module->prefs_changed);
1096 /* If any of them changed, indicate that we must redissect and refilter
1097 the current capture (if we have one), as the preference change
1098 could cause packets to be dissected differently. */
1099 if (module->prefs_changed)
1100 *must_redissect_p = TRUE;
1102 return 0; /* keep fetching module preferences */
1107 * This function is used to apply changes and update the Wireless Toolbar
1108 * whenever we apply some changes to the WEP preferences
1111 prefs_airpcap_update(void)
1113 GtkWidget *decryption_cm;
1114 GtkWidget *decryption_en;
1115 gboolean wireshark_decryption_was_enabled = FALSE;
1116 gboolean airpcap_decryption_was_enabled = FALSE;
1117 gboolean wireshark_decryption_is_now_enabled = FALSE;
1119 decryption_cm = GTK_WIDGET(g_object_get_data(G_OBJECT(airpcap_tb),AIRPCAP_TOOLBAR_DECRYPTION_KEY));
1120 decryption_en = GTK_WIDGET(GTK_ENTRY(GTK_COMBO(decryption_cm)->entry));
1122 if( g_ascii_strcasecmp(gtk_entry_get_text(GTK_ENTRY(decryption_en)),AIRPCAP_DECRYPTION_TYPE_STRING_WIRESHARK) == 0 )
1124 wireshark_decryption_was_enabled = TRUE;
1125 airpcap_decryption_was_enabled = FALSE;
1127 else if( g_ascii_strcasecmp(gtk_entry_get_text(GTK_ENTRY(decryption_en)),AIRPCAP_DECRYPTION_TYPE_STRING_AIRPCAP) == 0 )
1129 wireshark_decryption_was_enabled = FALSE;
1130 airpcap_decryption_was_enabled = TRUE;
1132 else if( g_ascii_strcasecmp(gtk_entry_get_text(GTK_ENTRY(decryption_en)),AIRPCAP_DECRYPTION_TYPE_STRING_NONE) == 0 )
1134 wireshark_decryption_was_enabled = FALSE;
1135 airpcap_decryption_was_enabled = FALSE;
1138 wireshark_decryption_is_now_enabled = wireshark_decryption_on();
1140 if(wireshark_decryption_is_now_enabled && airpcap_decryption_was_enabled)
1142 set_airpcap_decryption(FALSE);
1143 gtk_entry_set_text(GTK_ENTRY(decryption_en),AIRPCAP_DECRYPTION_TYPE_STRING_WIRESHARK);
1145 if(wireshark_decryption_is_now_enabled && !airpcap_decryption_was_enabled)
1147 set_airpcap_decryption(FALSE);
1148 gtk_entry_set_text(GTK_ENTRY(decryption_en),AIRPCAP_DECRYPTION_TYPE_STRING_WIRESHARK);
1150 else if(!wireshark_decryption_is_now_enabled && wireshark_decryption_was_enabled)
1152 if(airpcap_decryption_was_enabled)
1154 set_airpcap_decryption(TRUE);
1155 gtk_entry_set_text(GTK_ENTRY(decryption_en),AIRPCAP_DECRYPTION_TYPE_STRING_AIRPCAP);
1159 set_airpcap_decryption(FALSE);
1160 gtk_entry_set_text(GTK_ENTRY(decryption_en),AIRPCAP_DECRYPTION_TYPE_STRING_NONE);
1167 pref_clean(pref_t *pref, gpointer user_data _U_)
1169 switch (pref->type) {
1181 if (pref->saved_val.string != NULL) {
1182 g_free(pref->saved_val.string);
1183 pref->saved_val.string = NULL;
1188 if (pref->saved_val.range != NULL) {
1189 g_free(pref->saved_val.range);
1190 pref->saved_val.range = NULL;
1194 case PREF_STATIC_TEXT:
1199 g_assert_not_reached();
1206 module_prefs_clean(module_t *module, gpointer user_data _U_)
1208 /* For all preferences in this module, clean up any cruft allocated for
1209 use by the GUI code. */
1210 prefs_pref_foreach(module, pref_clean, NULL);
1211 return 0; /* keep cleaning modules */
1214 /* fetch all pref values from all pages */
1216 prefs_main_fetch_all(GtkWidget *dlg, gboolean *must_redissect)
1220 /* First, check that the values are all valid. */
1221 /* XXX - check the non-registered preferences too */
1222 switch (prefs_modules_foreach(module_prefs_check, (gpointer)&badpref)) {
1224 case PREFS_SET_SYNTAX_ERR:
1225 switch (badpref->type) {
1228 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1229 "The value for \"%s\" isn't a valid number.",
1234 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1235 "The value for \"%s\" isn't a valid range.",
1240 g_assert_not_reached();
1245 /* Fetch the preferences (i.e., make sure all the values set in all of
1246 the preferences panes have been copied to "prefs" and the registered
1248 gui_prefs_fetch(g_object_get_data(G_OBJECT(dlg), E_GUI_PAGE_KEY));
1249 layout_prefs_fetch(g_object_get_data(G_OBJECT(dlg), E_GUI_LAYOUT_PAGE_KEY));
1250 column_prefs_fetch(g_object_get_data(G_OBJECT(dlg), E_GUI_COLUMN_PAGE_KEY));
1251 stream_prefs_fetch(g_object_get_data(G_OBJECT(dlg), E_GUI_COLORS_PAGE_KEY));
1255 /* Is WPcap loaded? */
1258 capture_prefs_fetch(g_object_get_data(G_OBJECT(dlg), E_CAPTURE_PAGE_KEY));
1262 #endif /* HAVE_LIBPCAP */
1263 printer_prefs_fetch(g_object_get_data(G_OBJECT(dlg), E_PRINT_PAGE_KEY));
1264 nameres_prefs_fetch(g_object_get_data(G_OBJECT(dlg), E_NAMERES_PAGE_KEY));
1265 stats_prefs_fetch(g_object_get_data(G_OBJECT(dlg), E_TAPS_PAGE_KEY));
1266 protocols_prefs_fetch(g_object_get_data(G_OBJECT(dlg), E_PROTOCOLS_PAGE_KEY));
1267 prefs_modules_foreach(module_prefs_fetch, must_redissect);
1272 /* apply all pref values to the real world */
1274 prefs_main_apply_all(GtkWidget *dlg, gboolean redissect)
1279 * Apply the protocol preferences first - "gui_prefs_apply()" could
1280 * cause redissection, and we have to make sure the protocol
1281 * preference changes have been fully applied.
1285 gui_prefs_apply(g_object_get_data(G_OBJECT(dlg), E_GUI_PAGE_KEY), redissect);
1286 layout_prefs_apply(g_object_get_data(G_OBJECT(dlg), E_GUI_LAYOUT_PAGE_KEY));
1287 column_prefs_apply(g_object_get_data(G_OBJECT(dlg), E_GUI_COLUMN_PAGE_KEY));
1288 stream_prefs_apply(g_object_get_data(G_OBJECT(dlg), E_GUI_COLORS_PAGE_KEY));
1289 #ifndef NEW_PACKET_LIST
1290 /* With the old packet list, we need to do some calculations to figure out
1291 * the column sizes. But we don't want to do it until after we've set the
1292 * fonts (so we know how much room is needed) and we don't want to do it
1293 * until after we've applied the column preferences (so we know which
1294 * columns are there).
1296 packet_list_set_default_column_sizes();
1301 /* Is WPcap loaded? */
1304 capture_prefs_apply(g_object_get_data(G_OBJECT(dlg), E_CAPTURE_PAGE_KEY));
1308 #endif /* HAVE_LIBPCAP */
1309 printer_prefs_apply(g_object_get_data(G_OBJECT(dlg), E_PRINT_PAGE_KEY));
1310 nameres_prefs_apply(g_object_get_data(G_OBJECT(dlg), E_NAMERES_PAGE_KEY));
1311 stats_prefs_apply(g_object_get_data(G_OBJECT(dlg), E_TAPS_PAGE_KEY));
1312 protocols_prefs_apply(g_object_get_data(G_OBJECT(dlg), E_PROTOCOLS_PAGE_KEY));
1314 /* show/hide the Save button - depending on setting */
1315 save_bt = g_object_get_data(G_OBJECT(prefs_w), E_PREFSW_SAVE_BT_KEY);
1316 if(prefs.gui_use_pref_save) {
1317 gtk_widget_show(save_bt);
1319 gtk_widget_hide(save_bt);
1324 /* destroy all preferences ressources from all pages */
1326 prefs_main_destroy_all(GtkWidget *dlg)
1332 (frame = gtk_notebook_get_nth_page(g_object_get_data(G_OBJECT(prefs_w), E_PREFSW_NOTEBOOK_KEY), page_num)) != NULL;
1334 if(g_object_get_data(G_OBJECT(frame), E_PAGE_ITER_KEY))
1335 gtk_tree_iter_free(g_object_get_data(G_OBJECT(frame), E_PAGE_ITER_KEY));
1338 gui_prefs_destroy(g_object_get_data(G_OBJECT(dlg), E_GUI_PAGE_KEY));
1339 layout_prefs_destroy(g_object_get_data(G_OBJECT(dlg), E_GUI_LAYOUT_PAGE_KEY));
1340 column_prefs_destroy(g_object_get_data(G_OBJECT(dlg), E_GUI_COLUMN_PAGE_KEY));
1341 stream_prefs_destroy(g_object_get_data(G_OBJECT(dlg), E_GUI_COLORS_PAGE_KEY));
1345 /* Is WPcap loaded? */
1348 capture_prefs_destroy(g_object_get_data(G_OBJECT(dlg), E_CAPTURE_PAGE_KEY));
1352 #endif /* HAVE_LIBPCAP */
1353 printer_prefs_destroy(g_object_get_data(G_OBJECT(dlg), E_PRINT_PAGE_KEY));
1354 nameres_prefs_destroy(g_object_get_data(G_OBJECT(dlg), E_NAMERES_PAGE_KEY));
1355 stats_prefs_destroy(g_object_get_data(G_OBJECT(dlg), E_TAPS_PAGE_KEY));
1357 /* Free up the saved preferences (both for "prefs" and for registered
1359 free_prefs(&saved_prefs);
1360 prefs_modules_foreach(module_prefs_clean, NULL);
1361 protocols_prefs_destroy(g_object_get_data(G_OBJECT(dlg), E_PROTOCOLS_PAGE_KEY));
1366 pref_copy(pref_t *pref, gpointer user_data _U_)
1368 switch (pref->type) {
1371 pref->saved_val.uint = *pref->varp.uint;
1375 pref->saved_val.boolval = *pref->varp.boolp;
1379 pref->saved_val.enumval = *pref->varp.enump;
1383 g_free(pref->saved_val.string);
1384 pref->saved_val.string = g_strdup(*pref->varp.string);
1388 g_free(pref->saved_val.range);
1389 pref->saved_val.range = range_copy(*pref->varp.range);
1392 case PREF_STATIC_TEXT:
1397 g_assert_not_reached();
1404 module_prefs_copy(module_t *module, gpointer user_data _U_)
1406 /* For all preferences in this module, (re)save current value */
1407 prefs_pref_foreach(module, pref_copy, NULL);
1408 return 0; /* continue making copies */
1411 /* Copy prefs to saved values so we can revert to these values */
1412 /* if the user selects Cancel. */
1413 static void prefs_copy(void) {
1414 free_prefs(&saved_prefs);
1415 copy_prefs(&saved_prefs, &prefs);
1416 prefs_modules_foreach(module_prefs_copy, NULL);
1421 prefs_main_write(void)
1427 /* Create the directory that holds personal configuration files, if
1429 if (create_persconffile_dir(&pf_dir_path) == -1) {
1430 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1431 "Can't create directory\n\"%s\"\nfor preferences file: %s.", pf_dir_path,
1433 g_free(pf_dir_path);
1435 /* Write the preferencs out. */
1436 err = write_prefs(&pf_path);
1438 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1439 "Can't open preferences file\n\"%s\": %s.", pf_path,
1447 * Load the Wireshark decryption keys (just set) and save
1448 * the changes to the adapters' registry
1450 airpcap_load_decryption_keys(airpcap_if_list);
1456 prefs_main_ok_cb(GtkWidget *ok_bt _U_, gpointer parent_w)
1458 gboolean must_redissect = FALSE;
1460 if (!prefs_main_fetch_all(parent_w, &must_redissect))
1461 return; /* Errors in some preference setting - already reported */
1463 /* if we don't have a Save button, just save the settings now */
1464 if (!prefs.gui_use_pref_save) {
1468 prefs_main_apply_all(parent_w, must_redissect);
1470 /* Fill in capture options with values from the preferences */
1471 prefs_to_capture_opts();
1474 prefs_airpcap_update();
1477 /* Now destroy the "Preferences" dialog. */
1478 window_destroy(GTK_WIDGET(parent_w));
1480 if (must_redissect) {
1481 /* Redissect all the packets, and re-evaluate the display filter. */
1482 redissect_packets();
1488 prefs_main_apply_cb(GtkWidget *apply_bt _U_, gpointer parent_w)
1490 gboolean must_redissect = FALSE;
1492 if (!prefs_main_fetch_all(parent_w, &must_redissect))
1493 return; /* Errors in some preference setting - already reported */
1495 /* if we don't have a Save button, just save the settings now */
1496 if (!prefs.gui_use_pref_save) {
1498 prefs_copy(); /* save prefs for reverting if Cancel */
1501 prefs_main_apply_all(parent_w, must_redissect);
1503 /* Fill in capture options with values from the preferences */
1504 prefs_to_capture_opts();
1507 prefs_airpcap_update();
1510 if (must_redissect) {
1511 /* Redissect all the packets, and re-evaluate the display filter. */
1512 redissect_packets();
1517 prefs_main_save_cb(GtkWidget *save_bt _U_, gpointer parent_w)
1519 gboolean must_redissect = FALSE;
1521 if (!prefs_main_fetch_all(parent_w, &must_redissect))
1522 return; /* Errors in some preference setting - already reported */
1525 prefs_copy(); /* save prefs for reverting if Cancel */
1527 /* Now apply those preferences.
1528 XXX - should we do this? The user didn't click "OK" or "Apply".
1531 1) by saving the preferences they presumably indicate that they
1534 2) the next time they fire Wireshark up, those preferences will
1537 3) we'd have to buffer "must_redissect" so that if they do
1538 "Apply" after this, we know we have to redissect;
1540 4) we did apply the protocol preferences, at least, in the past. */
1541 prefs_main_apply_all(parent_w, must_redissect);
1543 /* Fill in capture options with values from the preferences */
1544 prefs_to_capture_opts();
1546 if (must_redissect) {
1547 /* Redissect all the packets, and re-evaluate the display filter. */
1548 redissect_packets();
1553 pref_revert(pref_t *pref, gpointer user_data)
1555 gboolean *pref_changed_p = user_data;
1557 /* Revert the preference to its saved value. */
1558 switch (pref->type) {
1561 if (*pref->varp.uint != pref->saved_val.uint) {
1562 *pref_changed_p = TRUE;
1563 *pref->varp.uint = pref->saved_val.uint;
1568 if (*pref->varp.boolp != pref->saved_val.boolval) {
1569 *pref_changed_p = TRUE;
1570 *pref->varp.boolp = pref->saved_val.boolval;
1575 if (*pref->varp.enump != pref->saved_val.enumval) {
1576 *pref_changed_p = TRUE;
1577 *pref->varp.enump = pref->saved_val.enumval;
1582 if (strcmp(*pref->varp.string, pref->saved_val.string) != 0) {
1583 *pref_changed_p = TRUE;
1584 g_free((void *)*pref->varp.string);
1585 *pref->varp.string = g_strdup(pref->saved_val.string);
1590 if (!ranges_are_equal(*pref->varp.range, pref->saved_val.range)) {
1591 *pref_changed_p = TRUE;
1592 g_free(*pref->varp.range);
1593 *pref->varp.range = range_copy(pref->saved_val.range);
1597 case PREF_STATIC_TEXT:
1602 g_assert_not_reached();
1609 module_prefs_revert(module_t *module, gpointer user_data)
1611 gboolean *must_redissect_p = user_data;
1613 /* For all preferences in this module, revert its value to the value
1614 it had when we popped up the Preferences dialog. Find out whether
1615 this changes any of them. */
1616 module->prefs_changed = FALSE; /* assume none of them changed */
1617 prefs_pref_foreach(module, pref_revert, &module->prefs_changed);
1619 /* If any of them changed, indicate that we must redissect and refilter
1620 the current capture (if we have one), as the preference change
1621 could cause packets to be dissected differently. */
1622 if (module->prefs_changed)
1623 *must_redissect_p = TRUE;
1624 return 0; /* keep processing modules */
1627 /* cancel button pressed, revert prefs to saved and exit dialog */
1629 prefs_main_cancel_cb(GtkWidget *cancel_bt _U_, gpointer parent_w)
1631 gboolean must_redissect = FALSE;
1633 /* Free up the current preferences and copy the saved preferences to the
1634 current preferences. */
1636 copy_prefs(&prefs, &saved_prefs);
1637 cfile.cinfo.columns_changed = FALSE; /* [XXX: "columns_changed" should treally be stored in prefs struct ??] */
1639 /* Now revert the registered preferences. */
1640 prefs_modules_foreach(module_prefs_revert, &must_redissect);
1642 /* Now apply the reverted-to preferences. */
1643 prefs_main_apply_all(parent_w, must_redissect);
1645 window_destroy(GTK_WIDGET(parent_w));
1647 if (must_redissect) {
1648 /* Redissect all the packets, and re-evaluate the display filter. */
1649 redissect_packets();
1653 /* Treat this as a cancel, by calling "prefs_main_cancel_cb()" */
1655 prefs_main_delete_event_cb(GtkWidget *prefs_w_lcl, GdkEvent *event _U_,
1656 gpointer user_data _U_)
1658 prefs_main_cancel_cb(NULL, prefs_w_lcl);
1663 /* dialog *is* already destroyed, clean up memory and such */
1665 prefs_main_destroy_cb(GtkWidget *win _U_, gpointer parent_w)
1667 prefs_main_destroy_all(parent_w);
1669 /* Note that we no longer have a "Preferences" dialog box. */
1673 struct properties_data {
1679 module_search_properties(module_t *module, gpointer user_data)
1681 struct properties_data *p = (struct properties_data *)user_data;
1683 /* If this module has the specified title, remember it. */
1684 if (strcmp(module->title, p->title) == 0) {
1686 return 1; /* stops the search */
1689 if(prefs_module_has_submodules(module))
1690 return prefs_modules_foreach_submodules(module, module_search_properties, p);
1696 tree_expand_row(GtkTreeModel *model, GtkTreeView *tree_view, GtkTreeIter *iter)
1701 /* expand the parent first */
1702 if(gtk_tree_model_iter_parent(model, &parent, iter))
1703 tree_expand_row(model, tree_view, &parent);
1705 path = gtk_tree_model_get_path(model, iter);
1706 gtk_tree_view_expand_row(tree_view, path, FALSE);
1707 /*expand_tree(tree_view, &parent, NULL, NULL);*/
1709 gtk_tree_path_free(path);
1712 /* select a node in the tree view */
1713 /* XXX - this is almost 100% copied from byte_view_select() in proto_draw.c,
1714 * find a way to combine both to have a generic function for this */
1716 tree_select_node(GtkWidget *tree, prefs_tree_iter *iter)
1718 GtkTreeIter local_iter = *iter;
1719 GtkTreeView *tree_view = GTK_TREE_VIEW(tree);
1720 GtkTreeModel *model;
1721 GtkTreePath *first_path;
1723 model = gtk_tree_view_get_model(tree_view);
1725 /* Expand our field's row */
1726 first_path = gtk_tree_model_get_path(model, &local_iter);
1728 /* expand from the top down */
1729 tree_expand_row(model, tree_view, &local_iter);
1731 /* select our field's row */
1732 gtk_tree_selection_select_path(gtk_tree_view_get_selection(tree_view),
1735 /* And position the window so the selection is visible.
1736 * Position the selection in the middle of the viewable
1738 gtk_tree_view_scroll_to_cell(tree_view, first_path, NULL, TRUE, 0.5f, 0.0f);
1740 gtk_tree_path_free(first_path);
1744 /* search the corresponding protocol page of the currently selected field */
1746 properties_cb(GtkWidget *w, gpointer dummy)
1748 header_field_info *hfinfo;
1750 struct properties_data p;
1754 module_t *page_module;
1756 if (cfile.finfo_selected == NULL) {
1757 /* There is no field selected */
1761 /* Find the title for the protocol for the selected field. */
1762 hfinfo = cfile.finfo_selected->hfinfo;
1763 if (hfinfo->parent == -1)
1764 title = prefs_get_title_by_name(hfinfo->abbrev);
1766 title = prefs_get_title_by_name(proto_registrar_get_abbrev(hfinfo->parent));
1768 return; /* Couldn't find it. XXX - just crash? "Can't happen"? */
1770 /* Find the module for that protocol by searching for one with that title.
1771 XXX - should we just associate protocols with modules directly? */
1774 prefs_modules_foreach_submodules(protocols_module, module_search_properties,
1776 if (p.module == NULL) {
1777 /* We didn't find it - that protocol probably has no preferences. */
1781 /* Create a preferences window, or pop up an existing one. */
1782 if (prefs_w != NULL) {
1783 reactivate_window(prefs_w);
1788 /* Search all the pages in that window for the one with the specified
1791 (sw = gtk_notebook_get_nth_page(g_object_get_data(G_OBJECT(prefs_w), E_PREFSW_NOTEBOOK_KEY), page_num)) != NULL;
1793 /* Get the frame from the scrollable window */
1794 frame = g_object_get_data(G_OBJECT(sw), E_PAGESW_FRAME_KEY);
1795 /* Get the module for this page (non-protocol prefs don't have one). */
1797 page_module = g_object_get_data(G_OBJECT(frame), E_PAGE_MODULE_KEY);
1798 if (page_module != NULL) {
1799 if (page_module == p.module) {
1801 g_object_get_data(G_OBJECT(prefs_w), E_PREFSW_TREE_KEY),
1802 g_object_get_data(G_OBJECT(frame), E_PAGE_ITER_KEY));
1810 /* Prefs tree selection callback. The node data has been loaded with
1811 the proper notebook page to load. */
1813 prefs_tree_select_cb(GtkTreeSelection *sel, gpointer dummy _U_)
1816 GtkTreeModel *model;
1819 if (gtk_tree_selection_get_selected(sel, &model, &iter))
1821 gtk_tree_model_get(model, &iter, 1, &page, -1);
1823 gtk_notebook_set_current_page(g_object_get_data(G_OBJECT(prefs_w), E_PREFSW_NOTEBOOK_KEY), page);
1834 * indent-tabs-mode: nil
1837 * ex: set shiftwidth=2 tabstop=8 expandtab
1838 * :indentSize=2:tabSize=8:noTabs=true: