GTK: Wrap static preference labels.
[metze/wireshark/wip.git] / ui / gtk / prefs_dlg.c
index 696dc9aceaab580d8f56737b273ee8ba4cd0b8f9..0437a2b4f81ee0603f90a52804f41149ad6f52d1 100644 (file)
@@ -1,8 +1,6 @@
 /* prefs_dlg.c
  * Routines for handling preferences
  *
- * $Id$
- *
  * Wireshark - Network traffic analyzer
  * By Gerald Combs <gerald@wireshark.org>
  * Copyright 1998 Gerald Combs
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
+#include "config.h"
 
 #include <gtk/gtk.h>
 
+#include <stdlib.h>
 #include <string.h>
 
-#include <epan/filesystem.h>
 #include <epan/packet.h>
 #include <epan/prefs.h>
-#include <epan/strutil.h>
 #include <epan/prefs-int.h>
+#include <epan/epan_dissect.h>
+#include <epan/decode_as.h>
 
-#include "../file.h"
-#include "../print.h"
-#include "ui/simple_dialog.h"
+#include "ui/preference_utils.h"
 
+#include "ui/gtk/old-gtk-compat.h"
 #include "ui/gtk/main.h"
 #include "ui/gtk/prefs_column.h"
 #include "ui/gtk/prefs_dlg.h"
 #include "ui/gtk/prefs_filter_expressions.h"
-#include "ui/gtk/prefs_print.h"
-#include "ui/gtk/prefs_stream.h"
+#include "ui/gtk/prefs_font_color.h"
 #include "ui/gtk/prefs_gui.h"
 #include "ui/gtk/prefs_layout.h"
 #include "ui/gtk/prefs_capture.h"
-#include "ui/gtk/prefs_nameres.h"
-#include "ui/gtk/prefs_taps.h"
-#include "ui/gtk/prefs_protocols.h"
 #include "ui/gtk/gui_utils.h"
 #include "ui/gtk/dlg_utils.h"
 #include "ui/gtk/stock_icons.h"
 #include "ui/gtk/help_dlg.h"
 #include "ui/gtk/keys.h"
 #include "ui/gtk/uat_gui.h"
-#include "ui/gtk/old-gtk-compat.h"
+#include "ui/gtk/file_dlg.h"
+#include "ui/gtk/packet_win.h"
+#include "simple_dialog.h"
 
 #ifdef HAVE_LIBPCAP
 #ifdef _WIN32
-#include "capture-wpcap.h"
+#include <caputils/capture-wpcap.h>
 #endif /* _WIN32 */
 #ifdef HAVE_AIRPCAP
-#include "airpcap.h"
-#include "airpcap_loader.h"
+#include <caputils/airpcap.h>
+#include <caputils/airpcap_loader.h>
 #include "airpcap_gui_utils.h"
 #endif
 #endif
@@ -79,6 +73,8 @@ static gboolean prefs_main_delete_event_cb(GtkWidget *, GdkEvent *, gpointer);
 static void     prefs_main_destroy_cb(GtkWidget *, gpointer);
 static void     prefs_tree_select_cb(GtkTreeSelection *, gpointer);
 
+static GtkWidget *create_preference_path_entry(GtkWidget *, int,
+   const gchar *, const gchar *, char *, gboolean);
 
 #define E_PREFSW_SCROLLW_KEY          "prefsw_scrollw"
 #define E_PREFSW_TREE_KEY             "prefsw_tree"
@@ -92,13 +88,11 @@ static void     prefs_tree_select_cb(GtkTreeSelection *, gpointer);
 #define E_GUI_LAYOUT_PAGE_KEY         "gui_layout_page"
 #define E_GUI_COLUMN_PAGE_KEY         "gui_column_options_page"
 #define E_GUI_FONT_PAGE_KEY           "gui_font_options_page"
-#define E_GUI_COLORS_PAGE_KEY         "gui_colors_options_page"
+#define E_GUI_FONT_COLORS_PAGE_KEY    "gui_font_colors_options_page"
 #define E_CAPTURE_PAGE_KEY            "capture_options_page"
-#define E_PRINT_PAGE_KEY              "printer_options_page"
 #define E_NAMERES_PAGE_KEY            "nameres_options_page"
-#define E_TAPS_PAGE_KEY               "taps_options_page"
-#define E_PROTOCOLS_PAGE_KEY          "protocols_options_page"
 #define E_FILTER_EXPRESSIONS_PAGE_KEY "filter_expressions_page"
+#define E_GRID_MODULE_KEY             "grid_module"
 
 /*
  * Keep a static pointer to the current "Preferences" window, if any, so that
@@ -108,168 +102,227 @@ static void     prefs_tree_select_cb(GtkTreeSelection *, gpointer);
  */
 static GtkWidget *prefs_w;
 
-/*
- * Save the value of the preferences as of when the preferences dialog
- * box was first popped up, so we can revert to those values if the
- * user selects "Cancel".
- */
-static e_prefs saved_prefs;
-
 struct ct_struct {
   GtkWidget    *main_vb;
   GtkWidget    *notebook;
   GtkWidget    *tree;
-  GtkTreeIter  iter;
-  gint         page;
-  gboolean     is_protocol;
+  GtkTreeIter   iter;
+  gint          page;
+  GtkTreeStore *store;
 };
 
-static gint protocols_page = 0;
-
 static guint
 pref_exists(pref_t *pref _U_, gpointer user_data _U_)
 {
   return 1;
 }
 
-/* show a single preference on the GtkTable of a preference page */
+/* show a single preference on the GtkGrid of a preference page */
 static guint
 pref_show(pref_t *pref, gpointer user_data)
 {
-  GtkWidget *main_tb = user_data;
+  GtkWidget  *main_grid = (GtkWidget *)user_data;
+  module_t   *module  = (module_t *)g_object_get_data(G_OBJECT(main_grid), E_GRID_MODULE_KEY);
   const char *title;
-  char *label_string;
-  size_t label_len;
-  char uint_str[10+1];
+  const char *type_name = prefs_pref_type_name(pref);
+  char       *label_string;
+  size_t      label_len;
+  char       *uint_str;
+  char *tooltip_txt;
 
   /* Give this preference a label which is its title, followed by a colon,
      and left-align it. */
-  title = pref->title;
+  title = prefs_get_title(pref);
   label_len = strlen(title) + 2;
-  label_string = g_malloc(label_len);
+  label_string = (char *)g_malloc(label_len);
   g_strlcpy(label_string, title, label_len);
 
+  tooltip_txt = prefs_get_description(pref) ? g_strdup_printf("%s\n\nName: %s.%s\nType: %s",
+                                                   prefs_get_description(pref),
+                                                   module->name,
+                                                   prefs_get_name(pref),
+                                                   type_name ? type_name : "Unknown"
+                                                   ): NULL;
+
   /*
    * Sometimes we don't want to append a ':' after a static text string...
    * If it is needed, we will specify it in the string itself.
    */
-  if(pref->type != PREF_STATIC_TEXT)
+  if (prefs_get_type(pref) != PREF_STATIC_TEXT)
     g_strlcat(label_string, ":", label_len);
 
+  pref_stash(pref, NULL);
+
   /* Save the current value of the preference, so that we can revert it if
      the user does "Apply" and then "Cancel", and create the control for
      editing the preference. */
-  switch (pref->type) {
+  switch (prefs_get_type(pref)) {
 
   case PREF_UINT:
-    pref->saved_val.uint = *pref->varp.uint;
-
+  case PREF_DECODE_AS_UINT:
     /* XXX - there are no uint spinbuttons, so we can't use a spinbutton.
        Even more annoyingly, even if there were, GLib doesn't define
        G_MAXUINT - but I think ANSI C may define UINT_MAX, so we could
        use that. */
-    switch (pref->info.base) {
-
-    case 10:
-      g_snprintf(uint_str, sizeof(uint_str), "%u", pref->saved_val.uint);
-      break;
-
-    case 8:
-      g_snprintf(uint_str, sizeof(uint_str), "%o", pref->saved_val.uint);
-      break;
-
-    case 16:
-      g_snprintf(uint_str, sizeof(uint_str), "%x", pref->saved_val.uint);
-      break;
-    }
-    pref->control = create_preference_entry(main_tb, pref->ordinal,
-                                            label_string, pref->description,
-                                            uint_str);
+    uint_str = prefs_pref_to_str(pref, pref_stashed);
+    prefs_set_control(pref, create_preference_entry(main_grid, prefs_get_ordinal(pref),
+                                            label_string, tooltip_txt,
+                                            uint_str));
+    g_free(uint_str);
     break;
 
   case PREF_BOOL:
-    pref->saved_val.boolval = *pref->varp.boolp;
-    pref->control = create_preference_check_button(main_tb, pref->ordinal,
-                                                   label_string, pref->description,
-                                                   pref->saved_val.boolval);
+    prefs_set_control(pref, create_preference_check_button(main_grid, prefs_get_ordinal(pref),
+                                                   label_string, tooltip_txt,
+                                                   prefs_get_bool_value(pref, pref_stashed)));
     break;
 
   case PREF_ENUM:
-    pref->saved_val.enumval = *pref->varp.enump;
-    if (pref->info.enum_info.radio_buttons) {
+    if (prefs_get_enum_radiobuttons(pref)) {
       /* Show it as radio buttons. */
-      pref->control = create_preference_radio_buttons(main_tb, pref->ordinal,
-                                                      label_string, pref->description,
-                                                      pref->info.enum_info.enumvals,
-                                                      pref->saved_val.enumval);
+      prefs_set_control(pref, create_preference_radio_buttons(main_grid, prefs_get_ordinal(pref),
+                                                      label_string, tooltip_txt,
+                                                      prefs_get_enumvals(pref),
+                                                      prefs_get_enum_value(pref, pref_stashed)));
     } else {
       /* Show it as an option menu. */
-      pref->control = create_preference_option_menu(main_tb, pref->ordinal,
-                                                    label_string, pref->description,
-                                                    pref->info.enum_info.enumvals,
-                                                    pref->saved_val.enumval);
+      prefs_set_control(pref, create_preference_option_menu(main_grid, prefs_get_ordinal(pref),
+                                                    label_string, tooltip_txt,
+                                                    prefs_get_enumvals(pref),
+                                                    prefs_get_enum_value(pref, pref_stashed)));
     }
     break;
 
   case PREF_STRING:
-    g_free(pref->saved_val.string);
-    pref->saved_val.string = g_strdup(*pref->varp.string);
-    pref->control = create_preference_entry(main_tb, pref->ordinal,
-                                            label_string, pref->description,
-                                            pref->saved_val.string);
+    prefs_set_control(pref, create_preference_entry(main_grid, prefs_get_ordinal(pref),
+                                            label_string, tooltip_txt,
+                                            prefs_get_string_value(pref, pref_stashed)));
+    break;
+
+  case PREF_FILENAME:
+    prefs_set_control(pref, create_preference_path_entry(main_grid, prefs_get_ordinal(pref),
+                                                     label_string,
+                                                     tooltip_txt,
+                                                     prefs_get_string_value(pref, pref_stashed), FALSE));
+    break;
+
+  case PREF_DIRNAME:
+    prefs_set_control(pref, create_preference_path_entry(main_grid, prefs_get_ordinal(pref),
+                                                     label_string,
+                                                     tooltip_txt,
+                                                     prefs_get_string_value(pref, pref_stashed), TRUE));
     break;
 
   case PREF_RANGE:
+  case PREF_DECODE_AS_RANGE:
   {
     char *range_str_p;
 
-    g_free(pref->saved_val.range);
-    pref->saved_val.range = range_copy(*pref->varp.range);
-    range_str_p = range_convert_range(*pref->varp.range);
-    pref->control = create_preference_entry(main_tb, pref->ordinal,
-                                            label_string, pref->description,
-                                            range_str_p);
+    range_str_p = range_convert_range(NULL, prefs_get_range_value_real(pref, pref_current));
+    prefs_set_control(pref, create_preference_entry(main_grid, prefs_get_ordinal(pref),
+                                            label_string, tooltip_txt,
+                                            range_str_p));
+    wmem_free(NULL, range_str_p);
     break;
   }
 
   case PREF_STATIC_TEXT:
   {
-    pref->control = create_preference_static_text(main_tb, pref->ordinal,
-                                                  label_string, pref->description);
+    prefs_set_control(pref, create_preference_static_text(main_grid, prefs_get_ordinal(pref),
+                                                  label_string, tooltip_txt));
     break;
   }
 
   case PREF_UAT:
   {
-    pref->control = create_preference_uat(main_tb, pref->ordinal,
-                                          label_string, pref->description,
-                                          pref->varp.uat);
+    if (prefs_get_gui_type(pref) == GUI_ALL || prefs_get_gui_type(pref) == GUI_GTK)
+        prefs_set_control(pref, create_preference_uat(main_grid, prefs_get_ordinal(pref),
+                                              label_string, tooltip_txt,
+                                              prefs_get_uat_value(pref)));
     break;
   }
 
+  case PREF_COLOR:
+  case PREF_CUSTOM:
+      /* currently not supported */
+
   case PREF_OBSOLETE:
     g_assert_not_reached();
     break;
   }
+  g_free(tooltip_txt);
   g_free(label_string);
 
   return 0;
 }
 
+#define prefs_tree_iter GtkTreeIter
+
+/* add a page to the tree */
+static prefs_tree_iter
+prefs_tree_page_add(const gchar *title, gint page_nr,
+                    gpointer store, prefs_tree_iter *parent_iter)
+{
+  prefs_tree_iter   iter;
+
+  gtk_tree_store_append((GtkTreeStore *)store, &iter, parent_iter);
+  gtk_tree_store_set((GtkTreeStore *)store, &iter, 0, title, 1, page_nr, -1);
+  return iter;
+}
+
+/* add a page to the notebook */
+static GtkWidget *
+prefs_nb_page_add(GtkWidget *notebook, const gchar *title _U_, GtkWidget *page, const char *page_key)
+{
+  GtkWidget         *sw;
+  GtkWidget         *frame;
+
+  sw = gtk_scrolled_window_new(NULL, NULL);
+  gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
+  gtk_widget_show(sw);
+
+  frame = gtk_frame_new(NULL);
+  gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_NONE);
+  gtk_container_set_border_width(GTK_CONTAINER(frame), DLG_OUTER_MARGIN);
+#if ! GTK_CHECK_VERSION(3,8,0)
+  gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(sw), frame);
+#else
+  gtk_container_add(GTK_CONTAINER(sw), frame);
+#endif
+  gtk_widget_show(frame);
+
+  if (page) {
+    gtk_container_add(GTK_CONTAINER(frame), page);
+    g_object_set_data(G_OBJECT(prefs_w), page_key, page);
+  }
+
+  gtk_notebook_append_page (GTK_NOTEBOOK(notebook), sw, NULL);
+
+  return sw;
+}
+
 #define MAX_TREE_NODE_NAME_LEN 64
+
 /* show prefs page for each registered module (protocol) */
 static guint
 module_prefs_show(module_t *module, gpointer user_data)
 {
-  struct ct_struct *cts = user_data;
-  struct ct_struct child_cts;
-  GtkWidget        *main_vb, *main_tb, *frame, *main_sw;
-  gchar            label_str[MAX_TREE_NODE_NAME_LEN];
+  struct ct_struct *cts = (struct ct_struct *)user_data;
+  struct ct_struct  child_cts;
+  GtkWidget        *main_vb, *main_grid, *frame, *main_sw;
+  gchar             label_str[MAX_TREE_NODE_NAME_LEN];
   GtkTreeStore     *model;
-  GtkTreeIter      iter;
+  GtkTreeIter       iter;
+
+  if (!module->use_gui) {
+      /* This module uses its own GUI interface to modify its
+       * preferences, so ignore it
+       */
+      return 0;
+  }
 
   /*
-   * Is this module a subtree, with modules underneath it?
+   * Is this module an interior node, with modules underneath it?
    */
   if (!prefs_module_has_submodules(module)) {
     /*
@@ -278,10 +331,12 @@ module_prefs_show(module_t *module, gpointer user_data)
      */
     if (prefs_pref_foreach(module, pref_exists, NULL) == 0) {
       /*
-       * No.  Don't put the module into the preferences window.
-       * XXX - we should do the same for subtrees; if a subtree has
-       * nothing under it that will be displayed, don't put it into
-       * the window.
+       * No.  Don't put the module into the preferences window,
+       * as there's nothing to show.
+       *
+       * XXX - we should do the same for interior ndes; if the module
+       * has no non-obsolete preferences *and* nothing under it has
+       * non-obsolete preferences, don't put it into the window.
        */
       return 0;
     }
@@ -292,19 +347,19 @@ module_prefs_show(module_t *module, gpointer user_data)
    */
   g_strlcpy(label_str, module->title, MAX_TREE_NODE_NAME_LEN);
   model = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(cts->tree)));
-  if (prefs_module_has_submodules(module) && !cts->iter.stamp)
+
+  if (module->parent == NULL)
     gtk_tree_store_append(model, &iter, NULL);
   else
     gtk_tree_store_append(model, &iter, &cts->iter);
 
   /*
-   * Is this a subtree?
+   * Is this an interior node?
    */
   if (prefs_module_has_submodules(module)) {
     /*
      * Yes.
      */
-
     gtk_tree_store_set(model, &iter, 0, label_str, 1, -1, -1);
 
     /*
@@ -312,100 +367,71 @@ module_prefs_show(module_t *module, gpointer user_data)
      */
     child_cts = *cts;
     child_cts.iter = iter;
-    if (module == protocols_module)
-      child_cts.is_protocol = TRUE;
     prefs_modules_foreach_submodules(module, module_prefs_show, &child_cts);
 
     /* keep the page count right */
     cts->page = child_cts.page;
-
   }
-  if(module->prefs) {
-    /*
-     * Has preferences.  Create a notebook page for it.
-     */
-
-    /* Scrolled window */
-    main_sw = gtk_scrolled_window_new(NULL, NULL);
-    gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(main_sw), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
-
-    /* Frame */
-    frame = gtk_frame_new(module->description);
-    gtk_container_set_border_width(GTK_CONTAINER(frame), 5);
-    gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(main_sw), frame);
-    g_object_set_data(G_OBJECT(main_sw), E_PAGESW_FRAME_KEY, frame);
 
-    /* Main vertical box */
-    main_vb = ws_gtk_box_new(GTK_ORIENTATION_VERTICAL, 5, FALSE);
-    gtk_container_set_border_width(GTK_CONTAINER(main_vb), 5);
-    gtk_container_add(GTK_CONTAINER(frame), main_vb);
-
-    /* Main table */
-    main_tb = gtk_table_new(module->numprefs, 2, FALSE);
-    gtk_box_pack_start(GTK_BOX(main_vb), main_tb, FALSE, FALSE, 0);
-    gtk_table_set_row_spacings(GTK_TABLE(main_tb), 10);
-    gtk_table_set_col_spacings(GTK_TABLE(main_tb), 15);
+  /*
+   * We create pages for interior nodes even if they don't have
+   * preferences, so that we at least have something to show
+   * if the user clicks on them, even if it's empty.
+   */
 
-    /* Add items for each of the preferences */
-    prefs_pref_foreach(module, pref_show, main_tb);
+  /* Scrolled window */
+  main_sw = gtk_scrolled_window_new(NULL, NULL);
+  gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(main_sw), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
 
-    /* Associate this module with the page's frame. */
-    g_object_set_data(G_OBJECT(frame), E_PAGE_MODULE_KEY, module);
+  /* Frame */
+  frame = gtk_frame_new(NULL);
+  gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_NONE);
+  gtk_container_set_border_width(GTK_CONTAINER(frame), DLG_OUTER_MARGIN);
+#if ! GTK_CHECK_VERSION(3,8,0)
+  gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(main_sw), frame);
+#else
+  gtk_container_add(GTK_CONTAINER(main_sw), frame);
+#endif
+  g_object_set_data(G_OBJECT(main_sw), E_PAGESW_FRAME_KEY, frame);
+
+  /* Main vertical box */
+  main_vb = ws_gtk_box_new(GTK_ORIENTATION_VERTICAL, 5, FALSE);
+  gtk_container_set_border_width(GTK_CONTAINER(main_vb), 5);
+  gtk_container_add(GTK_CONTAINER(frame), main_vb);
+
+  /* Main grid */
+  main_grid = ws_gtk_grid_new();
+  gtk_box_pack_start(GTK_BOX(main_vb), main_grid, FALSE, FALSE, 0);
+#if GTK_CHECK_VERSION(3,0,0)
+  gtk_widget_set_vexpand(GTK_WIDGET(main_grid), FALSE); /* Ignore VEXPAND requests from children */
+#endif
+  ws_gtk_grid_set_row_spacing(GTK_GRID(main_grid), 10);
+  ws_gtk_grid_set_column_spacing(GTK_GRID(main_grid), 15);
 
-    /* Add the page to the notebook */
-    gtk_notebook_append_page(GTK_NOTEBOOK(cts->notebook), main_sw, NULL);
+  /* Add items for each of the preferences */
+  g_object_set_data(G_OBJECT(main_grid), E_GRID_MODULE_KEY, module);
+  prefs_pref_foreach(module, pref_show, main_grid);
+  g_object_set_data(G_OBJECT(main_grid), E_GRID_MODULE_KEY, NULL);
 
-    /* Attach the page to the tree item */
-    gtk_tree_store_set(model, &iter, 0, label_str, 1, cts->page, -1);
-    g_object_set_data(G_OBJECT(frame), E_PAGE_ITER_KEY, gtk_tree_iter_copy(&iter));
+  /* Associate this module with the page's frame. */
+  g_object_set_data(G_OBJECT(frame), E_PAGE_MODULE_KEY, module);
 
-    cts->page++;
+  /* Add the page to the notebook */
+  gtk_notebook_append_page(GTK_NOTEBOOK(cts->notebook), main_sw, NULL);
 
-    /* Show 'em what we got */
-    gtk_widget_show_all(main_sw);
-  } else {
-    /* show the protocols page */
+  /* Attach the page to the tree item */
+  gtk_tree_store_set(model, &iter, 0, label_str, 1, cts->page, -1);
+  g_object_set_data(G_OBJECT(frame), E_PAGE_ITER_KEY, gtk_tree_iter_copy(&iter));
 
-    gtk_tree_store_set(model, &iter, 0, label_str, 1, protocols_page, -1);
+  cts->page++;
 
-  }
+  /* Show 'em what we got */
+  gtk_widget_show_all(main_sw);
 
   return 0;
 }
 
 
-#define prefs_tree_iter GtkTreeIter
-
-/* add a page to the tree */
-static prefs_tree_iter
-prefs_tree_page_add(const gchar *title, gint page_nr,
-                    gpointer store, prefs_tree_iter *parent_iter)
-{
-  prefs_tree_iter   iter;
-
-  gtk_tree_store_append(store, &iter, parent_iter);
-  gtk_tree_store_set(store, &iter, 0, title, 1, page_nr, -1);
-  return iter;
-}
-
-/* add a page to the notebook */
-static GtkWidget *
-prefs_nb_page_add(GtkWidget *notebook, const gchar *title, GtkWidget *page, const char *page_key)
-{
-  GtkWidget         *frame;
-
-  frame = gtk_frame_new(title);
-  gtk_widget_show(frame);
-  if(page) {
-    gtk_container_add(GTK_CONTAINER(frame), page);
-    g_object_set_data(G_OBJECT(prefs_w), page_key, page);
-  }
-  gtk_notebook_append_page (GTK_NOTEBOOK(notebook), frame, NULL);
-
-  return frame;
-}
-
-
 /* show the dialog */
 void
 prefs_cb(GtkWidget *w, gpointer dummy)
@@ -418,16 +444,16 @@ prefs_page_cb(GtkWidget *w _U_, gpointer dummy _U_, PREFS_PAGE_E prefs_page)
 {
   GtkWidget         *top_hb, *bbox, *prefs_nb, *ct_sb,
                     *ok_bt, *apply_bt, *save_bt, *cancel_bt, *help_bt;
-  GtkWidget         *gui_font_pg;
-  gchar             label_str[MAX_TREE_NODE_NAME_LEN];
-  struct ct_struct  cts;
+  gchar              label_str[MAX_TREE_NODE_NAME_LEN];
+  struct ct_struct   cts;
   GtkTreeStore      *store;
   GtkTreeSelection  *selection;
   GtkCellRenderer   *renderer;
   GtkTreeViewColumn *column;
-  gint              col_offset;
-  prefs_tree_iter   gui_iter, layout_iter, columns_iter;
-  gint              layout_page, columns_page;
+  gint               col_offset;
+  prefs_tree_iter    gui_iter, layout_iter, columns_iter, capture_iter;
+  gint               layout_page, columns_page;
+  gint               capture_page = 0;
 
 
   if (prefs_w != NULL) {
@@ -436,15 +462,12 @@ prefs_page_cb(GtkWidget *w _U_, gpointer dummy _U_, PREFS_PAGE_E prefs_page)
     return;
   }
 
-  /* Save the current preferences, so we can revert to those values
-     if the user presses "Cancel". */
-  copy_prefs(&saved_prefs, &prefs);
-
   prefs_w = dlg_conf_window_new("Wireshark: Preferences");
+  gtk_window_set_default_size(GTK_WINDOW(prefs_w), 400, 650);
 
   /*
-   * Unfortunately, we can't arrange that a GtkTable widget wrap an event box
-   * around a table row, so the spacing between the preference item's label
+   * Unfortunately, we can't arrange that a GtkGrid widget wrap an event box
+   * around a grid row, so the spacing between the preference item's label
    * and its control widgets is inactive and the tooltip doesn't pop up when
    * the mouse is over it.
    */
@@ -457,7 +480,7 @@ prefs_page_cb(GtkWidget *w _U_, gpointer dummy _U_, PREFS_PAGE_E prefs_page)
 
   /* Top row: Preferences tree and notebook */
   top_hb = ws_gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 10, FALSE);
-  gtk_container_add(GTK_CONTAINER(cts.main_vb), top_hb);
+  gtk_box_pack_start(GTK_BOX(cts.main_vb), top_hb, TRUE, TRUE, 0);
   gtk_widget_show(top_hb);
 
   /* scrolled window on the left for the categories tree */
@@ -466,7 +489,7 @@ prefs_page_cb(GtkWidget *w _U_, gpointer dummy _U_, PREFS_PAGE_E prefs_page)
                                    GTK_SHADOW_IN);
   gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(ct_sb),
                                  GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
-  gtk_container_add(GTK_CONTAINER(top_hb), ct_sb);
+  gtk_box_pack_start(GTK_BOX(top_hb), ct_sb, TRUE, TRUE, 0);
   gtk_widget_show(ct_sb);
   g_object_set_data(G_OBJECT(prefs_w), E_PREFSW_SCROLLW_KEY, ct_sb);
 
@@ -495,16 +518,11 @@ prefs_page_cb(GtkWidget *w _U_, gpointer dummy _U_, PREFS_PAGE_E prefs_page)
   g_object_set_data(G_OBJECT(prefs_w), E_PREFSW_NOTEBOOK_KEY, prefs_nb);
   gtk_notebook_set_show_tabs(GTK_NOTEBOOK(prefs_nb), FALSE);
   gtk_notebook_set_show_border(GTK_NOTEBOOK(prefs_nb), FALSE);
-  gtk_container_add(GTK_CONTAINER(top_hb), prefs_nb);
+  gtk_box_pack_start(GTK_BOX(top_hb), prefs_nb, TRUE, TRUE, 0);
   gtk_widget_show(prefs_nb);
 
   cts.page = 0;
 
-  /* Preferences common for all protocols */
-  g_strlcpy(label_str, "Protocols", MAX_TREE_NODE_NAME_LEN);
-  prefs_nb_page_add(prefs_nb, label_str, protocols_prefs_show(), E_PROTOCOLS_PAGE_KEY);
-  protocols_page = cts.page++;
-
   /* GUI prefs */
   g_strlcpy(label_str, "User Interface", MAX_TREE_NODE_NAME_LEN);
   prefs_nb_page_add(prefs_nb, label_str, gui_prefs_show(), E_GUI_PAGE_KEY);
@@ -523,34 +541,13 @@ prefs_page_cb(GtkWidget *w _U_, gpointer dummy _U_, PREFS_PAGE_E prefs_page)
   columns_iter = prefs_tree_page_add(label_str, cts.page, store, &gui_iter);
   columns_page = cts.page++;
 
-  /* GUI Font prefs */
-  g_strlcpy(label_str, "Font", MAX_TREE_NODE_NAME_LEN);
-  gui_font_pg = gui_font_prefs_show();
-  prefs_nb_page_add(prefs_nb, label_str, gui_font_pg, E_GUI_FONT_PAGE_KEY);
-  prefs_tree_page_add(label_str, cts.page, store, &gui_iter);
-  cts.page++;
-
-  gtk_container_set_border_width( GTK_CONTAINER(gui_font_pg), 5 );
-
-  /* IMPORTANT: the following gtk_font_selection_set_font_name() function will
-     only work if the widget and it's corresponding window is already shown
-     (so don't put the following into gui_font_prefs_show()) !!! */
-
-  /* We set the current font now, because setting it appears not to work
-     when run before appending the frame to the notebook. */
-#if GTK_CHECK_VERSION(3,2,0)
-  gtk_font_chooser_set_font(GTK_FONT_CHOOSER(gui_font_pg), prefs.gui_font_name);
-#else
-  gtk_font_selection_set_font_name(
-    GTK_FONT_SELECTION(gui_font_pg), prefs.gui_font_name);
-#endif /* GTK_CHECK_VERSION(3,2,0) */
   /* GUI Colors prefs */
-  g_strlcpy(label_str, "Colors", MAX_TREE_NODE_NAME_LEN);
-  prefs_nb_page_add(prefs_nb, label_str, stream_prefs_show(), E_GUI_COLORS_PAGE_KEY);
+  g_strlcpy(label_str, "Font and Colors", MAX_TREE_NODE_NAME_LEN);
+  prefs_nb_page_add(prefs_nb, label_str, font_color_prefs_show(), E_GUI_FONT_COLORS_PAGE_KEY);
   prefs_tree_page_add(label_str, cts.page, store, &gui_iter);
   cts.page++;
 
-  /* select the main GUI page as the default page and expand it's children */
+  /* select the main GUI page as the default page and expand its children */
   gtk_tree_selection_select_iter(selection, &gui_iter);
   /* (expand will only take effect, when at least one child exists) */
   gtk_tree_view_expand_all(GTK_TREE_VIEW(cts.tree));
@@ -563,25 +560,13 @@ prefs_page_cb(GtkWidget *w _U_, gpointer dummy _U_, PREFS_PAGE_E prefs_page)
   /* capture prefs */
   g_strlcpy(label_str, "Capture", MAX_TREE_NODE_NAME_LEN);
   prefs_nb_page_add(prefs_nb, label_str, capture_prefs_show(), E_CAPTURE_PAGE_KEY);
-  prefs_tree_page_add(label_str, cts.page, store, NULL);
-  cts.page++;
+  capture_iter = prefs_tree_page_add(label_str, cts.page, store, NULL);
+  capture_page = cts.page++;
 #ifdef _WIN32
   }
 #endif /* _WIN32 */
 #endif /* HAVE_LIBPCAP */
 
-  /* Printing prefs */
-  g_strlcpy(label_str, "Printing", MAX_TREE_NODE_NAME_LEN);
-  prefs_nb_page_add(prefs_nb, label_str, printer_prefs_show(), E_PRINT_PAGE_KEY);
-  prefs_tree_page_add(label_str, cts.page, store, NULL);
-  cts.page++;
-
-  /* Name resolution prefs */
-  g_strlcpy(label_str, "Name Resolution", MAX_TREE_NODE_NAME_LEN);
-  prefs_nb_page_add(prefs_nb, label_str, nameres_prefs_show(), E_NAMERES_PAGE_KEY);
-  prefs_tree_page_add(label_str, cts.page, store, NULL);
-  cts.page++;
-
   /* Saved filter prefs */
   g_strlcpy(label_str, "Filter Expressions", MAX_TREE_NODE_NAME_LEN);
   prefs_nb_page_add(prefs_nb, label_str, filter_expressions_prefs_show(),
@@ -589,15 +574,9 @@ prefs_page_cb(GtkWidget *w _U_, gpointer dummy _U_, PREFS_PAGE_E prefs_page)
   prefs_tree_page_add(label_str, cts.page, store, NULL);
   cts.page++;
 
-  /* TAPS player prefs */
-  g_strlcpy(label_str, "Statistics", MAX_TREE_NODE_NAME_LEN);
-  prefs_nb_page_add(prefs_nb, label_str, stats_prefs_show(), E_TAPS_PAGE_KEY);
-  prefs_tree_page_add(label_str, cts.page, store, NULL);
-  cts.page++;
-
   /* Registered prefs */
   cts.notebook = prefs_nb;
-  cts.is_protocol = FALSE;
+  cts.store = store;
   prefs_modules_foreach_submodules(NULL, module_prefs_show, &cts);
 
   /* Button row: OK and alike buttons */
@@ -605,23 +584,23 @@ prefs_page_cb(GtkWidget *w _U_, gpointer dummy _U_, PREFS_PAGE_E prefs_page)
   gtk_box_pack_start(GTK_BOX(cts.main_vb), bbox, FALSE, FALSE, 0);
   gtk_widget_show(bbox);
 
-  ok_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_OK);
+  ok_bt = (GtkWidget *)g_object_get_data(G_OBJECT(bbox), GTK_STOCK_OK);
   g_signal_connect(ok_bt, "clicked", G_CALLBACK(prefs_main_ok_cb), prefs_w);
 
-  apply_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_APPLY);
+  apply_bt = (GtkWidget *)g_object_get_data(G_OBJECT(bbox), GTK_STOCK_APPLY);
   g_signal_connect(apply_bt, "clicked", G_CALLBACK(prefs_main_apply_cb), prefs_w);
 
-  save_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_SAVE);
+  save_bt = (GtkWidget *)g_object_get_data(G_OBJECT(bbox), GTK_STOCK_SAVE);
   g_signal_connect(save_bt, "clicked", G_CALLBACK(prefs_main_save_cb), prefs_w);
   g_object_set_data(G_OBJECT(prefs_w), E_PREFSW_SAVE_BT_KEY, save_bt);
 
-  cancel_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_CANCEL);
+  cancel_bt = (GtkWidget *)g_object_get_data(G_OBJECT(bbox), GTK_STOCK_CANCEL);
   g_signal_connect(cancel_bt, "clicked", G_CALLBACK(prefs_main_cancel_cb), prefs_w);
   window_set_cancel_button(prefs_w, cancel_bt, NULL);
 
   gtk_widget_grab_default(ok_bt);
 
-  help_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_HELP);
+  help_bt = (GtkWidget *)g_object_get_data(G_OBJECT(bbox), GTK_STOCK_HELP);
   g_signal_connect(help_bt, "clicked", G_CALLBACK(topic_cb), (gpointer)HELP_PREFERENCES_DIALOG);
 
   g_signal_connect(prefs_w, "delete_event", G_CALLBACK(prefs_main_delete_event_cb), NULL);
@@ -630,7 +609,7 @@ prefs_page_cb(GtkWidget *w _U_, gpointer dummy _U_, PREFS_PAGE_E prefs_page)
   gtk_widget_show(prefs_w);
 
   /* hide the Save button if the user uses implicit save */
-  if(!prefs.gui_use_pref_save) {
+  if (!prefs.gui_use_pref_save) {
     gtk_widget_hide(save_bt);
   }
 
@@ -639,11 +618,17 @@ prefs_page_cb(GtkWidget *w _U_, gpointer dummy _U_, PREFS_PAGE_E prefs_page)
   switch (prefs_page) {
   case PREFS_PAGE_LAYOUT:
     gtk_tree_selection_select_iter(selection, &layout_iter);
-    gtk_notebook_set_current_page(g_object_get_data(G_OBJECT(prefs_w), E_PREFSW_NOTEBOOK_KEY), layout_page);
+    gtk_notebook_set_current_page((GtkNotebook *)g_object_get_data(G_OBJECT(prefs_w), E_PREFSW_NOTEBOOK_KEY), layout_page);
     break;
   case PREFS_PAGE_COLUMNS:
     gtk_tree_selection_select_iter(selection, &columns_iter);
-    gtk_notebook_set_current_page(g_object_get_data(G_OBJECT(prefs_w), E_PREFSW_NOTEBOOK_KEY), columns_page);
+    gtk_notebook_set_current_page((GtkNotebook *)g_object_get_data(G_OBJECT(prefs_w), E_PREFSW_NOTEBOOK_KEY), columns_page);
+    break;
+  case PREFS_PAGE_CAPTURE:
+    if (capture_page) {
+      gtk_tree_selection_select_iter(selection, &capture_iter);
+      gtk_notebook_set_current_page((GtkNotebook *)g_object_get_data(G_OBJECT(prefs_w), E_PREFSW_NOTEBOOK_KEY), capture_page);
+    }
     break;
   default:
     /* Not implemented yet */
@@ -654,7 +639,7 @@ prefs_page_cb(GtkWidget *w _U_, gpointer dummy _U_, PREFS_PAGE_E prefs_page)
 }
 
 static void
-set_option_label(GtkWidget *main_tb, int table_position,
+set_option_label(GtkWidget *main_grid, int grid_position,
     const gchar *label_text, const gchar *tooltip_text)
 {
   GtkWidget *label;
@@ -666,8 +651,7 @@ set_option_label(GtkWidget *main_tb, int table_position,
 
   event_box = gtk_event_box_new();
   gtk_event_box_set_visible_window (GTK_EVENT_BOX(event_box), FALSE);
-  gtk_table_attach_defaults(GTK_TABLE(main_tb), event_box, 0, 1,
-                            table_position, table_position + 1);
+  ws_gtk_grid_attach_defaults(GTK_GRID(main_grid), event_box, 0, grid_position, 1, 1);
   if (tooltip_text != NULL)
     gtk_widget_set_tooltip_text(event_box, tooltip_text);
   gtk_container_add(GTK_CONTAINER(event_box), label);
@@ -675,17 +659,16 @@ set_option_label(GtkWidget *main_tb, int table_position,
 }
 
 GtkWidget *
-create_preference_check_button(GtkWidget *main_tb, int table_position,
+create_preference_check_button(GtkWidget *main_grid, int grid_position,
     const gchar *label_text, const gchar *tooltip_text, gboolean active)
 {
   GtkWidget *check_box;
 
-  set_option_label(main_tb, table_position, label_text, tooltip_text);
+  set_option_label(main_grid, grid_position, label_text, tooltip_text);
 
   check_box = gtk_check_button_new();
   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check_box), active);
-  gtk_table_attach_defaults(GTK_TABLE(main_tb), check_box, 1, 2,
-                            table_position, table_position + 1);
+  ws_gtk_grid_attach_defaults(GTK_GRID(main_grid), check_box, 1, grid_position, 1, 1);
   if (tooltip_text != NULL)
     gtk_widget_set_tooltip_text(check_box, tooltip_text);
 
@@ -693,17 +676,17 @@ create_preference_check_button(GtkWidget *main_tb, int table_position,
 }
 
 GtkWidget *
-create_preference_radio_buttons(GtkWidget *main_tb, int table_position,
+create_preference_radio_buttons(GtkWidget *main_grid, int grid_position,
     const gchar *label_text, const gchar *tooltip_text,
     const enum_val_t *enumvals, gint current_val)
 {
-  GtkWidget *radio_button_hbox, *button = NULL;
-  GSList *rb_group;
-  int idx;
+  GtkWidget        *radio_button_hbox, *button = NULL;
+  GSList           *rb_group;
+  int               idx;
   const enum_val_t *enum_valp;
-  GtkWidget *event_box;
+  GtkWidget        *event_box;
 
-  set_option_label(main_tb, table_position, label_text, tooltip_text);
+  set_option_label(main_grid, grid_position, label_text, tooltip_text);
 
   radio_button_hbox = ws_gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0, FALSE);
   rb_group = NULL;
@@ -725,8 +708,7 @@ create_preference_radio_buttons(GtkWidget *main_tb, int table_position,
   event_box = gtk_event_box_new();
   gtk_event_box_set_visible_window (GTK_EVENT_BOX(event_box), FALSE);
   gtk_container_add(GTK_CONTAINER(event_box), radio_button_hbox);
-  gtk_table_attach_defaults(GTK_TABLE(main_tb), event_box, 1, 2,
-                            table_position, table_position+1);
+  ws_gtk_grid_attach_defaults(GTK_GRID(main_grid), event_box, 1, grid_position, 1, 1);
   if (tooltip_text != NULL)
     gtk_widget_set_tooltip_text(event_box, tooltip_text);
   gtk_widget_show(event_box);
@@ -775,7 +757,7 @@ fetch_preference_radio_buttons_val(GtkWidget *button,
   button = NULL;
   for (rb_entry = rb_group; rb_entry != NULL;
        rb_entry = g_slist_next(rb_entry)) {
-    button = rb_entry->data;
+    button = (GtkWidget *)rb_entry->data;
     if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button)))
       break;
   }
@@ -785,16 +767,16 @@ fetch_preference_radio_buttons_val(GtkWidget *button,
 }
 
 GtkWidget *
-create_preference_option_menu(GtkWidget *main_tb, int table_position,
+create_preference_option_menu(GtkWidget *main_grid, int grid_position,
     const gchar *label_text, const gchar *tooltip_text,
     const enum_val_t *enumvals, gint current_val)
 {
-  GtkWidget *menu_box, *combo_box;
-  int menu_idx, idx;
+  GtkWidget        *menu_box, *combo_box;
+  int               menu_idx, idx;
   const enum_val_t *enum_valp;
-  GtkWidget *event_box;
+  GtkWidget        *event_box;
 
-  set_option_label(main_tb, table_position, label_text, tooltip_text);
+  set_option_label(main_grid, grid_position, label_text, tooltip_text);
 
   /* Create a menu from the enumvals */
   combo_box = gtk_combo_box_text_new();
@@ -812,7 +794,7 @@ create_preference_option_menu(GtkWidget *main_tb, int table_position,
 
   /*
    * Put the combo box in an hbox, so that it's only as wide
-   * as the widest entry, rather than being as wide as the table
+   * as the widest entry, rather than being as wide as the grid
    * space.
    */
   menu_box = ws_gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0, FALSE);
@@ -820,8 +802,7 @@ create_preference_option_menu(GtkWidget *main_tb, int table_position,
 
   event_box = gtk_event_box_new();
   gtk_event_box_set_visible_window (GTK_EVENT_BOX(event_box), FALSE);
-  gtk_table_attach_defaults(GTK_TABLE(main_tb), event_box,
-                            1, 2, table_position, table_position + 1);
+  ws_gtk_grid_attach_defaults(GTK_GRID(main_grid), event_box, 1, grid_position, 1, 1);
   if (tooltip_text != NULL)
     gtk_widget_set_tooltip_text(event_box, tooltip_text);
   gtk_container_add(GTK_CONTAINER(event_box), menu_box);
@@ -844,18 +825,17 @@ fetch_preference_option_menu_val(GtkWidget *combo_box, const enum_val_t *enumval
 }
 
 GtkWidget *
-create_preference_entry(GtkWidget *main_tb, int table_position,
+create_preference_entry(GtkWidget *main_grid, int grid_position,
     const gchar *label_text, const gchar *tooltip_text, char *value)
 {
   GtkWidget *entry;
 
-  set_option_label(main_tb, table_position, label_text, tooltip_text);
+  set_option_label(main_grid, grid_position, label_text, tooltip_text);
 
   entry = gtk_entry_new();
   if (value != NULL)
     gtk_entry_set_text(GTK_ENTRY(entry), value);
-  gtk_table_attach_defaults(GTK_TABLE(main_tb), entry, 1, 2,
-                            table_position, table_position + 1);
+  ws_gtk_grid_attach_defaults(GTK_GRID(main_grid), entry, 1, grid_position, 1, 1);
   if (tooltip_text != NULL)
     gtk_widget_set_tooltip_text(entry, tooltip_text);
   gtk_widget_show(entry);
@@ -863,18 +843,69 @@ create_preference_entry(GtkWidget *main_tb, int table_position,
   return entry;
 }
 
+static void
+preference_filename_entry_cb(GtkWidget *button, GtkWidget *filename_te)
+{
+    /* XXX - use a better browser dialog title */
+    file_selection_browse(button, filename_te, "Wireshark: File preference",
+                          FILE_SELECTION_READ_BROWSE);
+}
+
+static void
+preference_dirname_entry_cb(GtkWidget *button, GtkWidget *filename_te)
+{
+    /* XXX - use a better browser dialog title */
+    file_selection_browse(button, filename_te, "Wireshark: Directory preference",
+                          FILE_SELECTION_CREATE_FOLDER);
+}
+
+static GtkWidget *
+create_preference_path_entry(GtkWidget *main_grid, int grid_position,
+    const gchar *label_text, const gchar *tooltip_text, char *value, gboolean dir_only)
+{
+  GtkWidget *entry;
+  GtkWidget *button, *file_bt_hb;
+
+  set_option_label(main_grid, grid_position, label_text, tooltip_text);
+  file_bt_hb = ws_gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0, FALSE);
+  ws_gtk_grid_attach_defaults(GTK_GRID(main_grid), file_bt_hb, 1, grid_position, 1, 1);
+  gtk_widget_show(file_bt_hb);
+
+  button = ws_gtk_button_new_from_stock(WIRESHARK_STOCK_BROWSE);
+  gtk_box_pack_end(GTK_BOX(file_bt_hb), button, FALSE, FALSE, 0);
+  gtk_widget_show(button);
+
+  entry = gtk_entry_new();
+  gtk_box_pack_start(GTK_BOX(file_bt_hb), entry, TRUE, TRUE, 0);
+  if (value != NULL)
+    gtk_entry_set_text(GTK_ENTRY(entry), value);
+  if (tooltip_text != NULL)
+    gtk_widget_set_tooltip_text(entry, tooltip_text);
+  gtk_widget_show(entry);
+
+  if (dir_only) {
+    g_signal_connect(button, "clicked", G_CALLBACK(preference_dirname_entry_cb), entry);
+  } else {
+    g_signal_connect(button, "clicked", G_CALLBACK(preference_filename_entry_cb), entry);
+  }
+
+  return entry;
+}
+
 GtkWidget *
-create_preference_static_text(GtkWidget *main_tb, int table_position,
+create_preference_static_text(GtkWidget *main_grid, int grid_position,
     const gchar *label_text, const gchar *tooltip_text)
 {
   GtkWidget *label;
 
-  if(label_text != NULL)
+  if (label_text != NULL) {
     label = gtk_label_new(label_text);
-  else
+    gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
+    gtk_label_set_width_chars (GTK_LABEL (label), 80);
+  } else {
     label = gtk_label_new("");
-  gtk_table_attach_defaults(GTK_TABLE(main_tb), label, 0, 2,
-                            table_position, table_position + 1);
+  }
+  ws_gtk_grid_attach_defaults(GTK_GRID(main_grid), label, 0, grid_position, 2, 1);
   if (tooltip_text != NULL)
     gtk_widget_set_tooltip_text(label, tooltip_text);
   gtk_widget_show(label);
@@ -883,19 +914,18 @@ create_preference_static_text(GtkWidget *main_tb, int table_position,
 }
 
 GtkWidget *
-create_preference_uat(GtkWidget *main_tb, int table_position,
+create_preference_uat(GtkWidget *main_grid, int grid_position,
     const gchar *label_text, const gchar *tooltip_text, void* uat)
 {
-  GtkWidget *button = NULL;
+  GtkWidget *button;
 
-  set_option_label(main_tb, table_position, label_text, tooltip_text);
+  set_option_label(main_grid, grid_position, label_text, tooltip_text);
 
-  button = gtk_button_new_from_stock(WIRESHARK_STOCK_EDIT);
+  button = ws_gtk_button_new_from_stock(WIRESHARK_STOCK_EDIT);
 
   g_signal_connect(button, "clicked", G_CALLBACK(uat_window_cb), uat);
 
-  gtk_table_attach_defaults(GTK_TABLE(main_tb), button, 1, 2,
-                            table_position, table_position+1);
+  ws_gtk_grid_attach_defaults(GTK_GRID(main_grid), button, 1, grid_position, 1, 1);
   if (tooltip_text != NULL)
     gtk_widget_set_tooltip_text(button, tooltip_text);
   gtk_widget_show(button);
@@ -907,15 +937,16 @@ create_preference_uat(GtkWidget *main_tb, int table_position,
 static guint
 pref_check(pref_t *pref, gpointer user_data)
 {
-  const char *str_val;
-  char *p;
-  pref_t **badpref = user_data;
+  const char  *str_val;
+  char        *p;
+  pref_t     **badpref = (pref_t **)user_data;
 
   /* Fetch the value of the preference, and check whether it's valid. */
-  switch (pref->type) {
+  switch (prefs_get_type(pref)) {
 
   case PREF_UINT:
-    str_val = gtk_entry_get_text(GTK_ENTRY(pref->control));
+  case PREF_DECODE_AS_UINT:
+    str_val = gtk_entry_get_text(GTK_ENTRY(prefs_get_control(pref)));
     errno = 0;
 
     /* XXX: The following ugly hack prevents a gcc warning
@@ -931,7 +962,7 @@ pref_check(pref_t *pref, gpointer user_data)
          and thus avoiding the need to check whether it's a valid number, would also be a good idea."
        ]
     */
-    if(strtoul(str_val, &p, pref->info.base)){}
+    if (strtoul(str_val, &p, prefs_get_uint_base(pref))){}
     if (p == str_val || *p != '\0' || errno != 0) {
       *badpref = pref;
       return PREFS_SET_SYNTAX_ERR;      /* number was bad */
@@ -947,20 +978,24 @@ pref_check(pref_t *pref, gpointer user_data)
     break;
 
   case PREF_STRING:
+  case PREF_FILENAME:
+  case PREF_DIRNAME:
     /* Value can't be bad. */
     break;
 
   case PREF_RANGE:
-    str_val = gtk_entry_get_text(GTK_ENTRY(pref->control));
+  case PREF_DECODE_AS_RANGE:
+    str_val = gtk_entry_get_text(GTK_ENTRY(prefs_get_control(pref)));
 
     if (strlen(str_val) != 0) {
       range_t *newrange;
 
-      if (range_convert_str(&newrange, str_val, pref->info.max_value) != CVT_NO_ERROR) {
+      if (range_convert_str(NULL, &newrange, str_val, prefs_get_max_value(pref)) != CVT_NO_ERROR) {
         *badpref = pref;
+        wmem_free(NULL, newrange);
         return PREFS_SET_SYNTAX_ERR;    /* range was bad */
       }
-      g_free(newrange);
+      wmem_free(NULL, newrange);
     }
     break;
 
@@ -969,6 +1004,10 @@ pref_check(pref_t *pref, gpointer user_data)
     /* Value can't be bad. */
     break;
 
+  case PREF_COLOR:
+  case PREF_CUSTOM:
+      /* currently not supported */
+
   case PREF_OBSOLETE:
     g_assert_not_reached();
     break;
@@ -979,6 +1018,11 @@ pref_check(pref_t *pref, gpointer user_data)
 static guint
 module_prefs_check(module_t *module, gpointer user_data)
 {
+  /* Ignore any preferences with their own interface */
+  if (!module->use_gui) {
+      return 0;
+  }
+
   /* For all preferences in this module, fetch its value from this
      module's notebook page and check whether it's valid. */
   return prefs_pref_foreach(module, pref_check, user_data);
@@ -988,89 +1032,100 @@ static guint
 pref_fetch(pref_t *pref, gpointer user_data)
 {
   const char *str_val;
-  char *p;
-  guint uval;
-  gboolean bval;
-  gint enumval;
-  gboolean *pref_changed_p = user_data;
+  char       *p;
+  guint       uval, uval_stashed;
+  gboolean    bval;
+  gint        enumval;
+  module_t *module = (module_t *)user_data;
+  pref_unstash_data_t unstash_data;
 
   /* Fetch the value of the preference, and set the appropriate variable
      to it. */
-  switch (pref->type) {
+  switch (prefs_get_type(pref)) {
+
+  case PREF_DECODE_AS_UINT:
+    str_val = gtk_entry_get_text(GTK_ENTRY(prefs_get_control(pref)));
+    uval = (guint)strtoul(str_val, &p, prefs_get_uint_base(pref));
+#if 0
+    if (p == value || *p != '\0')
+      return PREFS_SET_SYNTAX_ERR;      /* number was bad */
+#endif
+    /* Save stashed value to use pref_unstash and restore it later */
+    uval_stashed = prefs_get_uint_value_real(pref, pref_stashed);
+    prefs_set_uint_value(pref, uval, pref_stashed);
+
+    unstash_data.module = module;
+    unstash_data.handle_decode_as = TRUE;
+    pref_unstash(pref, (gpointer)&unstash_data);
+
+    /* Restore stashed value */
+    prefs_set_uint_value(pref, uval_stashed, pref_stashed);
+    break;
 
   case PREF_UINT:
-    str_val = gtk_entry_get_text(GTK_ENTRY(pref->control));
-    uval = strtoul(str_val, &p, pref->info.base);
+    str_val = gtk_entry_get_text(GTK_ENTRY(prefs_get_control(pref)));
+    uval = (guint)strtoul(str_val, &p, prefs_get_uint_base(pref));
 #if 0
     if (p == value || *p != '\0')
       return PREFS_SET_SYNTAX_ERR;      /* number was bad */
 #endif
-    if (*pref->varp.uint != uval) {
-      *pref_changed_p = TRUE;
-      *pref->varp.uint = uval;
-    }
+    module->prefs_changed |= prefs_set_uint_value(pref, uval, pref_current);
     break;
 
   case PREF_BOOL:
-    bval = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(pref->control));
-    if (*pref->varp.boolp != bval) {
-      *pref_changed_p = TRUE;
-      *pref->varp.boolp = bval;
-    }
+    bval = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(prefs_get_control(pref)));
+    module->prefs_changed |= prefs_set_bool_value(pref, bval, pref_current);
     break;
 
   case PREF_ENUM:
-    if (pref->info.enum_info.radio_buttons) {
-      enumval = fetch_preference_radio_buttons_val(pref->control,
-          pref->info.enum_info.enumvals);
+    if (prefs_get_enum_radiobuttons(pref)) {
+      enumval = fetch_preference_radio_buttons_val((GtkWidget *)prefs_get_control(pref),
+          prefs_get_enumvals(pref));
     } else {
-      enumval = fetch_preference_option_menu_val(pref->control,
-                                                 pref->info.enum_info.enumvals);
+      enumval = fetch_preference_option_menu_val((GtkWidget *)prefs_get_control(pref),
+                                                 prefs_get_enumvals(pref));
     }
 
-    if (*pref->varp.enump != enumval) {
-      *pref_changed_p = TRUE;
-      *pref->varp.enump = enumval;
-    }
+    module->prefs_changed |= prefs_set_enum_value(pref, enumval, pref_current);
     break;
 
   case PREF_STRING:
-    str_val = gtk_entry_get_text(GTK_ENTRY(pref->control));
-    if (strcmp(*pref->varp.string, str_val) != 0) {
-      *pref_changed_p = TRUE;
-      g_free((void *)*pref->varp.string);
-      *pref->varp.string = g_strdup(str_val);
-    }
+  case PREF_FILENAME:
+  case PREF_DIRNAME:
+    str_val = gtk_entry_get_text(GTK_ENTRY(prefs_get_control(pref)));
+    module->prefs_changed |= prefs_set_string_value(pref, str_val, pref_current);
     break;
 
-  case PREF_RANGE:
-  {
-    range_t *newrange;
-    convert_ret_t ret;
+  case PREF_DECODE_AS_RANGE:
+    {
+    str_val = gtk_entry_get_text(GTK_ENTRY(prefs_get_control(pref)));
+
+    module->prefs_changed |= prefs_set_stashed_range_value(pref, str_val);
 
-    str_val = gtk_entry_get_text(GTK_ENTRY(pref->control));
-    ret = range_convert_str(&newrange, str_val, pref->info.max_value);
-    if (ret != CVT_NO_ERROR)
+    unstash_data.module = module;
+    unstash_data.handle_decode_as = TRUE;
+    pref_unstash(pref, (gpointer)&unstash_data);
+    break;
+    }
+  case PREF_RANGE:
+    str_val = gtk_entry_get_text(GTK_ENTRY(prefs_get_control(pref)));
+    if (!prefs_set_range_value_work(pref, str_val, TRUE, &module->prefs_changed))
 #if 0
       return PREFS_SET_SYNTAX_ERR;      /* range was bad */
 #else
       return 0; /* XXX - should fail */
 #endif
 
-    if (!ranges_are_equal(*pref->varp.range, newrange)) {
-      *pref_changed_p = TRUE;
-      g_free(*pref->varp.range);
-      *pref->varp.range = newrange;
-    } else
-      g_free(newrange);
-
     break;
-  }
 
   case PREF_STATIC_TEXT:
   case PREF_UAT:
     break;
 
+  case PREF_COLOR:
+  case PREF_CUSTOM:
+      /* currently not supported */
+
   case PREF_OBSOLETE:
     g_assert_not_reached();
     break;
@@ -1081,12 +1136,17 @@ pref_fetch(pref_t *pref, gpointer user_data)
 static guint
 module_prefs_fetch(module_t *module, gpointer user_data)
 {
-  gboolean *must_redissect_p = user_data;
+  gboolean *must_redissect_p = (gboolean *)user_data;
+
+  /* Ignore any preferences with their own interface */
+  if (!module->use_gui) {
+      return 0;
+  }
 
   /* For all preferences in this module, fetch its value from this
      module's notebook page.  Find out whether any of them changed. */
   module->prefs_changed = FALSE;        /* assume none of them changed */
-  prefs_pref_foreach(module, pref_fetch, &module->prefs_changed);
+  prefs_pref_foreach(module, pref_fetch, module);
 
   /* If any of them changed, indicate that we must redissect and refilter
      the current capture (if we have one), as the preference change
@@ -1106,12 +1166,12 @@ static void
 prefs_airpcap_update(void)
 {
   GtkWidget *decryption_cm;
-  gint cur_active;
-  gboolean wireshark_decryption_was_enabled = FALSE;
-  gboolean airpcap_decryption_was_enabled = FALSE;
-  gboolean wireshark_decryption_is_now_enabled = FALSE;
+  gint       cur_active;
+  gboolean   wireshark_decryption_was_enabled    = FALSE;
+  gboolean   airpcap_decryption_was_enabled      = FALSE;
+  gboolean   wireshark_decryption_is_now_enabled = FALSE;
 
-  decryption_cm = GTK_WIDGET(g_object_get_data(G_OBJECT(airpcap_tb),AIRPCAP_TOOLBAR_DECRYPTION_KEY));
+  decryption_cm = GTK_WIDGET(g_object_get_data(G_OBJECT(wireless_tb),AIRPCAP_TOOLBAR_DECRYPTION_KEY));
 
   if (decryption_cm == NULL) {
     return;
@@ -1141,19 +1201,19 @@ prefs_airpcap_update(void)
 
   wireshark_decryption_is_now_enabled = wireshark_decryption_on();
 
-  if(wireshark_decryption_is_now_enabled && airpcap_decryption_was_enabled)
+  if (wireshark_decryption_is_now_enabled && airpcap_decryption_was_enabled)
   {
     set_airpcap_decryption(FALSE);
     gtk_combo_box_set_active(GTK_COMBO_BOX(decryption_cm), 1);
   }
-  if(wireshark_decryption_is_now_enabled && !airpcap_decryption_was_enabled)
+  if (wireshark_decryption_is_now_enabled && !airpcap_decryption_was_enabled)
   {
     set_airpcap_decryption(FALSE);
     gtk_combo_box_set_active(GTK_COMBO_BOX(decryption_cm), 1);
   }
-  else if(!wireshark_decryption_is_now_enabled && wireshark_decryption_was_enabled)
+  else if (!wireshark_decryption_is_now_enabled && wireshark_decryption_was_enabled)
   {
-    if(airpcap_decryption_was_enabled)
+    if (airpcap_decryption_was_enabled)
     {
       set_airpcap_decryption(TRUE);
       gtk_combo_box_set_active(GTK_COMBO_BOX(decryption_cm), 2);
@@ -1168,50 +1228,16 @@ prefs_airpcap_update(void)
 #endif
 
 static guint
-pref_clean(pref_t *pref, gpointer user_data _U_)
+module_prefs_clean_stash(module_t *module, gpointer user_data _U_)
 {
-  switch (pref->type) {
-
-  case PREF_UINT:
-    break;
-
-  case PREF_BOOL:
-    break;
-
-  case PREF_ENUM:
-    break;
-
-  case PREF_STRING:
-    if (pref->saved_val.string != NULL) {
-      g_free(pref->saved_val.string);
-      pref->saved_val.string = NULL;
-    }
-    break;
-
-  case PREF_RANGE:
-    if (pref->saved_val.range != NULL) {
-      g_free(pref->saved_val.range);
-      pref->saved_val.range = NULL;
-    }
-    break;
-
-  case PREF_STATIC_TEXT:
-  case PREF_UAT:
-    break;
-
-  case PREF_OBSOLETE:
-    g_assert_not_reached();
-    break;
+  /* Ignore any preferences with their own interface */
+  if (!module->use_gui) {
+      return 0;
   }
-  return 0;
-}
 
-static guint
-module_prefs_clean(module_t *module, gpointer user_data _U_)
-{
   /* For all preferences in this module, clean up any cruft allocated for
      use by the GUI code. */
-  prefs_pref_foreach(module, pref_clean, NULL);
+  prefs_pref_foreach(module, pref_clean_stash, NULL);
   return 0;     /* keep cleaning modules */
 }
 
@@ -1225,19 +1251,21 @@ prefs_main_fetch_all(GtkWidget *dlg, gboolean *must_redissect)
   /* XXX - check the non-registered preferences too */
   switch (prefs_modules_foreach(module_prefs_check, (gpointer)&badpref)) {
 
-  case PREFS_SET_SYNTAX_ERR:
-    switch (badpref->type) {
+    case PREFS_SET_SYNTAX_ERR:
+      switch (prefs_get_type(badpref)) {
 
     case PREF_UINT:
+    case PREF_DECODE_AS_UINT:
       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
                     "The value for \"%s\" isn't a valid number.",
-                    badpref->title);
+                    prefs_get_title(badpref));
       return FALSE;
 
     case PREF_RANGE:
+    case PREF_DECODE_AS_RANGE:
       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
                     "The value for \"%s\" isn't a valid range.",
-                    badpref->title);
+                    prefs_get_title(badpref));
       return FALSE;
 
     default:
@@ -1249,27 +1277,23 @@ prefs_main_fetch_all(GtkWidget *dlg, gboolean *must_redissect)
   /* Fetch the preferences (i.e., make sure all the values set in all of
      the preferences panes have been copied to "prefs" and the registered
      preferences). */
-  gui_prefs_fetch(g_object_get_data(G_OBJECT(dlg), E_GUI_PAGE_KEY));
-  layout_prefs_fetch(g_object_get_data(G_OBJECT(dlg), E_GUI_LAYOUT_PAGE_KEY));
-  column_prefs_fetch(g_object_get_data(G_OBJECT(dlg), E_GUI_COLUMN_PAGE_KEY));
-  stream_prefs_fetch(g_object_get_data(G_OBJECT(dlg), E_GUI_COLORS_PAGE_KEY));
+  gui_prefs_fetch((GtkWidget *)g_object_get_data(G_OBJECT(dlg), E_GUI_PAGE_KEY));
+  layout_prefs_fetch((GtkWidget *)g_object_get_data(G_OBJECT(dlg), E_GUI_LAYOUT_PAGE_KEY));
+  column_prefs_fetch((GtkWidget *)g_object_get_data(G_OBJECT(dlg), E_GUI_COLUMN_PAGE_KEY));
+  font_color_prefs_fetch((GtkWidget *)g_object_get_data(G_OBJECT(dlg), E_GUI_FONT_COLORS_PAGE_KEY));
 
 #ifdef HAVE_LIBPCAP
 #ifdef _WIN32
   /* Is WPcap loaded? */
   if (has_wpcap) {
 #endif /* _WIN32 */
-  capture_prefs_fetch(g_object_get_data(G_OBJECT(dlg), E_CAPTURE_PAGE_KEY));
+  capture_prefs_fetch((GtkWidget *)g_object_get_data(G_OBJECT(dlg), E_CAPTURE_PAGE_KEY));
 #ifdef _WIN32
   }
 #endif /* _WIN32 */
 #endif /* HAVE_LIBPCAP */
-  printer_prefs_fetch(g_object_get_data(G_OBJECT(dlg), E_PRINT_PAGE_KEY));
-  nameres_prefs_fetch(g_object_get_data(G_OBJECT(dlg), E_NAMERES_PAGE_KEY));
-  filter_expressions_prefs_fetch(g_object_get_data(G_OBJECT(dlg),
+  filter_expressions_prefs_fetch((GtkWidget *)g_object_get_data(G_OBJECT(dlg),
     E_FILTER_EXPRESSIONS_PAGE_KEY));
-  stats_prefs_fetch(g_object_get_data(G_OBJECT(dlg), E_TAPS_PAGE_KEY));
-  protocols_prefs_fetch(g_object_get_data(G_OBJECT(dlg), E_PROTOCOLS_PAGE_KEY));
   prefs_modules_foreach(module_prefs_fetch, must_redissect);
 
   return TRUE;
@@ -1288,29 +1312,25 @@ prefs_main_apply_all(GtkWidget *dlg, gboolean redissect)
    */
   prefs_apply_all();
 
-  gui_prefs_apply(g_object_get_data(G_OBJECT(dlg), E_GUI_PAGE_KEY), redissect);
-  layout_prefs_apply(g_object_get_data(G_OBJECT(dlg), E_GUI_LAYOUT_PAGE_KEY));
-  column_prefs_apply(g_object_get_data(G_OBJECT(dlg), E_GUI_COLUMN_PAGE_KEY));
-  stream_prefs_apply(g_object_get_data(G_OBJECT(dlg), E_GUI_COLORS_PAGE_KEY));
+  gui_prefs_apply((GtkWidget *)g_object_get_data(G_OBJECT(dlg), E_GUI_PAGE_KEY));
+  layout_prefs_apply((GtkWidget *)g_object_get_data(G_OBJECT(dlg), E_GUI_LAYOUT_PAGE_KEY));
+  column_prefs_apply((GtkWidget *)g_object_get_data(G_OBJECT(dlg), E_GUI_COLUMN_PAGE_KEY));
+  font_color_prefs_apply((GtkWidget *)g_object_get_data(G_OBJECT(dlg), E_GUI_FONT_COLORS_PAGE_KEY), redissect);
 
 #ifdef HAVE_LIBPCAP
 #ifdef _WIN32
   /* Is WPcap loaded? */
   if (has_wpcap) {
 #endif /* _WIN32 */
-  capture_prefs_apply(g_object_get_data(G_OBJECT(dlg), E_CAPTURE_PAGE_KEY));
+  capture_prefs_apply((GtkWidget *)g_object_get_data(G_OBJECT(dlg), E_CAPTURE_PAGE_KEY));
 #ifdef _WIN32
   }
 #endif /* _WIN32 */
 #endif /* HAVE_LIBPCAP */
-  printer_prefs_apply(g_object_get_data(G_OBJECT(dlg), E_PRINT_PAGE_KEY));
-  nameres_prefs_apply(g_object_get_data(G_OBJECT(dlg), E_NAMERES_PAGE_KEY));
-  stats_prefs_apply(g_object_get_data(G_OBJECT(dlg), E_TAPS_PAGE_KEY));
-  protocols_prefs_apply(g_object_get_data(G_OBJECT(dlg), E_PROTOCOLS_PAGE_KEY));
 
   /* show/hide the Save button - depending on setting */
-  save_bt = g_object_get_data(G_OBJECT(prefs_w), E_PREFSW_SAVE_BT_KEY);
-  if(prefs.gui_use_pref_save) {
+  save_bt = (GtkWidget *)g_object_get_data(G_OBJECT(prefs_w), E_PREFSW_SAVE_BT_KEY);
+  if (prefs.gui_use_pref_save) {
     gtk_widget_show(save_bt);
   } else {
     gtk_widget_hide(save_bt);
@@ -1322,147 +1342,134 @@ prefs_main_apply_all(GtkWidget *dlg, gboolean redissect)
 static void
 prefs_main_destroy_all(GtkWidget *dlg)
 {
-  int page_num;
+  int        page_num;
   GtkWidget *frame;
 
   for (page_num = 0;
-       (frame = gtk_notebook_get_nth_page(g_object_get_data(G_OBJECT(prefs_w), E_PREFSW_NOTEBOOK_KEY), page_num)) != NULL;
+       (frame = gtk_notebook_get_nth_page((GtkNotebook *)g_object_get_data(G_OBJECT(prefs_w), E_PREFSW_NOTEBOOK_KEY), page_num)) != NULL;
        page_num++) {
-    if(g_object_get_data(G_OBJECT(frame), E_PAGE_ITER_KEY))
-      gtk_tree_iter_free(g_object_get_data(G_OBJECT(frame), E_PAGE_ITER_KEY));
+    if (g_object_get_data(G_OBJECT(frame), E_PAGE_ITER_KEY))
+      gtk_tree_iter_free((GtkTreeIter *)g_object_get_data(G_OBJECT(frame), E_PAGE_ITER_KEY));
   }
 
-  gui_prefs_destroy(g_object_get_data(G_OBJECT(dlg), E_GUI_PAGE_KEY));
-  layout_prefs_destroy(g_object_get_data(G_OBJECT(dlg), E_GUI_LAYOUT_PAGE_KEY));
-  column_prefs_destroy(g_object_get_data(G_OBJECT(dlg), E_GUI_COLUMN_PAGE_KEY));
-  stream_prefs_destroy(g_object_get_data(G_OBJECT(dlg), E_GUI_COLORS_PAGE_KEY));
+  gui_prefs_destroy((GtkWidget *)g_object_get_data(G_OBJECT(dlg), E_GUI_PAGE_KEY));
+  layout_prefs_destroy((GtkWidget *)g_object_get_data(G_OBJECT(dlg), E_GUI_LAYOUT_PAGE_KEY));
+  column_prefs_destroy((GtkWidget *)g_object_get_data(G_OBJECT(dlg), E_GUI_COLUMN_PAGE_KEY));
+  font_color_prefs_destroy((GtkWidget *)g_object_get_data(G_OBJECT(dlg), E_GUI_FONT_COLORS_PAGE_KEY));
 
 #ifdef HAVE_LIBPCAP
 #ifdef _WIN32
   /* Is WPcap loaded? */
   if (has_wpcap) {
 #endif /* _WIN32 */
-  capture_prefs_destroy(g_object_get_data(G_OBJECT(dlg), E_CAPTURE_PAGE_KEY));
+  capture_prefs_destroy((GtkWidget *)g_object_get_data(G_OBJECT(dlg), E_CAPTURE_PAGE_KEY));
 #ifdef _WIN32
   }
 #endif /* _WIN32 */
 #endif /* HAVE_LIBPCAP */
-  printer_prefs_destroy(g_object_get_data(G_OBJECT(dlg), E_PRINT_PAGE_KEY));
-  nameres_prefs_destroy(g_object_get_data(G_OBJECT(dlg), E_NAMERES_PAGE_KEY));
-  stats_prefs_destroy(g_object_get_data(G_OBJECT(dlg), E_TAPS_PAGE_KEY));
 
   /* Free up the saved preferences (both for "prefs" and for registered
      preferences). */
-  free_prefs(&saved_prefs);
-  prefs_modules_foreach(module_prefs_clean, NULL);
-  protocols_prefs_destroy(g_object_get_data(G_OBJECT(dlg), E_PROTOCOLS_PAGE_KEY));
+  prefs_modules_foreach(module_prefs_clean_stash, NULL);
 }
 
-
 static guint
-pref_copy(pref_t *pref, gpointer user_data _U_)
+module_prefs_copy(module_t *module, gpointer user_data _U_)
 {
-  switch (pref->type) {
-
-  case PREF_UINT:
-    pref->saved_val.uint = *pref->varp.uint;
-    break;
-
-  case PREF_BOOL:
-    pref->saved_val.boolval = *pref->varp.boolp;
-    break;
-
-  case PREF_ENUM:
-    pref->saved_val.enumval = *pref->varp.enump;
-    break;
-
-  case PREF_STRING:
-    g_free(pref->saved_val.string);
-    pref->saved_val.string = g_strdup(*pref->varp.string);
-    break;
-
-  case PREF_RANGE:
-    g_free(pref->saved_val.range);
-    pref->saved_val.range = range_copy(*pref->varp.range);
-    break;
-
-  case PREF_STATIC_TEXT:
-  case PREF_UAT:
-    break;
-
-  case PREF_OBSOLETE:
-    g_assert_not_reached();
-    break;
+  /* Ignore any preferences with their own interface */
+  if (!module->use_gui) {
+      return 0;
   }
-  return 0;
-}
 
-static guint
-module_prefs_copy(module_t *module, gpointer user_data _U_)
-{
   /* For all preferences in this module, (re)save current value */
-  prefs_pref_foreach(module, pref_copy, NULL);
+  prefs_pref_foreach(module, pref_stash, NULL);
   return 0;     /* continue making copies */
 }
 
 /* Copy prefs to saved values so we can revert to these values */
 /*  if the user selects Cancel.                                */
 static void prefs_copy(void) {
-  free_prefs(&saved_prefs);
-  copy_prefs(&saved_prefs, &prefs);
   prefs_modules_foreach(module_prefs_copy, NULL);
 }
 
+static void
+overwrite_existing_prefs_cb(gpointer dialog _U_, gint btn, gpointer parent_w _U_)
+{
+  gchar* err = NULL;
 
-void
-prefs_main_write(void)
+  switch (btn) {
+    case(ESD_BTN_SAVE):
+      prefs_main_write();
+      prefs.unknown_prefs = FALSE;
+
+      if (save_decode_as_entries(&err) < 0)
+      {
+          simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", err);
+          g_free(err);
+      }
+      break;
+    case(ESD_BTN_DONT_SAVE):
+      break;
+    default:
+      g_assert_not_reached();
+  }
+}
+static void
+prefs_main_save(gpointer parent_w)
 {
-  int err;
-  char *pf_dir_path;
-  char *pf_path;
-
-  /* Create the directory that holds personal configuration files, if
-     necessary.  */
-  if (create_persconffile_dir(&pf_dir_path) == -1) {
-    simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
-                  "Can't create directory\n\"%s\"\nfor preferences file: %s.", pf_dir_path,
-                  g_strerror(errno));
-    g_free(pf_dir_path);
+  gchar* err = NULL;
+
+  if (prefs.unknown_prefs) {
+    gpointer dialog;
+    const gchar *msg =
+      "Obsolete or unrecognized preferences have been detected and will be "
+      "discarded when saving this profile. If you would like to preserve "
+      "these preferences for a different Wireshark version, click "
+      "'Continue without Saving' and save this profile under a different name.";
+
+    if (prefs.saved_at_version) {
+      dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_SAVE_DONTSAVE,
+          "These preferences were last saved at version \"%s\".\n%s",
+          prefs.saved_at_version, msg);
+    } else {
+      dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_SAVE_DONTSAVE,
+          "%s", msg);
+    }
+
+    simple_dialog_set_cb(dialog, overwrite_existing_prefs_cb, parent_w);
   } else {
-    /* Write the preferencs out. */
-    err = write_prefs(&pf_path);
-    if (err != 0) {
-      simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
-                    "Can't open preferences file\n\"%s\": %s.", pf_path,
-                    g_strerror(err));
-      g_free(pf_path);
+    prefs_main_write();
+
+    if (save_decode_as_entries(&err) < 0)
+    {
+        simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", err);
+        g_free(err);
     }
   }
-
-#ifdef HAVE_AIRPCAP
-  /*
-   * Load the Wireshark decryption keys (just set) and save
-   * the changes to the adapters' registry
-   */
-  airpcap_load_decryption_keys(airpcap_if_list);
-#endif
 }
 
-
 static void
 prefs_main_ok_cb(GtkWidget *ok_bt _U_, gpointer parent_w)
 {
   gboolean must_redissect = FALSE;
 
-  if (!prefs_main_fetch_all(parent_w, &must_redissect))
+  if (!prefs_main_fetch_all((GtkWidget *)parent_w, &must_redissect))
     return; /* Errors in some preference setting - already reported */
 
   /* if we don't have a Save button, just save the settings now */
   if (!prefs.gui_use_pref_save) {
-    prefs_main_write();
+    prefs_main_save(parent_w);
   }
 
-  prefs_main_apply_all(parent_w, must_redissect);
+#ifdef HAVE_AIRPCAP
+  /*
+   * Load the Wireshark decryption keys (just set) and save
+   * the changes to the adapters' registry
+   */
+  airpcap_load_decryption_keys(g_airpcap_if_list);
+#endif
+
+  prefs_main_apply_all((GtkWidget *)parent_w, must_redissect);
 
   /* Fill in capture options with values from the preferences */
   prefs_to_capture_opts();
@@ -1477,6 +1484,7 @@ prefs_main_ok_cb(GtkWidget *ok_bt _U_, gpointer parent_w)
   if (must_redissect) {
     /* Redissect all the packets, and re-evaluate the display filter. */
     redissect_packets();
+    redissect_all_packet_windows();
   }
 
 }
@@ -1486,16 +1494,16 @@ prefs_main_apply_cb(GtkWidget *apply_bt _U_, gpointer parent_w)
 {
   gboolean must_redissect = FALSE;
 
-  if (!prefs_main_fetch_all(parent_w, &must_redissect))
+  if (!prefs_main_fetch_all((GtkWidget *)parent_w, &must_redissect))
     return; /* Errors in some preference setting - already reported */
 
   /* if we don't have a Save button, just save the settings now */
   if (!prefs.gui_use_pref_save) {
-    prefs_main_write();
+    prefs_main_save(parent_w);
     prefs_copy();     /* save prefs for reverting if Cancel */
   }
 
-  prefs_main_apply_all(parent_w, must_redissect);
+  prefs_main_apply_all((GtkWidget *)parent_w, must_redissect);
 
   /* Fill in capture options with values from the preferences */
   prefs_to_capture_opts();
@@ -1507,6 +1515,7 @@ prefs_main_apply_cb(GtkWidget *apply_bt _U_, gpointer parent_w)
   if (must_redissect) {
     /* Redissect all the packets, and re-evaluate the display filter. */
     redissect_packets();
+    redissect_all_packet_windows();
   }
 }
 
@@ -1515,10 +1524,10 @@ prefs_main_save_cb(GtkWidget *save_bt _U_, gpointer parent_w)
 {
   gboolean must_redissect = FALSE;
 
-  if (!prefs_main_fetch_all(parent_w, &must_redissect))
+  if (!prefs_main_fetch_all((GtkWidget *)parent_w, &must_redissect))
     return; /* Errors in some preference setting - already reported */
 
-  prefs_main_write();
+  prefs_main_save(parent_w);
   prefs_copy();     /* save prefs for reverting if Cancel */
 
   /* Now apply those preferences.
@@ -1535,7 +1544,7 @@ prefs_main_save_cb(GtkWidget *save_bt _U_, gpointer parent_w)
            "Apply" after this, we know we have to redissect;
 
         4) we did apply the protocol preferences, at least, in the past. */
-  prefs_main_apply_all(parent_w, must_redissect);
+  prefs_main_apply_all((GtkWidget *)parent_w, must_redissect);
 
   /* Fill in capture options with values from the preferences */
   prefs_to_capture_opts();
@@ -1543,75 +1552,28 @@ prefs_main_save_cb(GtkWidget *save_bt _U_, gpointer parent_w)
   if (must_redissect) {
     /* Redissect all the packets, and re-evaluate the display filter. */
     redissect_packets();
+    redissect_all_packet_windows();
   }
 }
 
 static guint
-pref_revert(pref_t *pref, gpointer user_data)
+module_prefs_revert(module_t *module, gpointer user_data)
 {
-  gboolean *pref_changed_p = user_data;
-
-  /* Revert the preference to its saved value. */
-  switch (pref->type) {
-
-  case PREF_UINT:
-    if (*pref->varp.uint != pref->saved_val.uint) {
-      *pref_changed_p = TRUE;
-      *pref->varp.uint = pref->saved_val.uint;
-    }
-    break;
-
-  case PREF_BOOL:
-    if (*pref->varp.boolp != pref->saved_val.boolval) {
-      *pref_changed_p = TRUE;
-      *pref->varp.boolp = pref->saved_val.boolval;
-    }
-    break;
-
-  case PREF_ENUM:
-    if (*pref->varp.enump != pref->saved_val.enumval) {
-      *pref_changed_p = TRUE;
-      *pref->varp.enump = pref->saved_val.enumval;
-    }
-    break;
-
-  case PREF_STRING:
-    if (strcmp(*pref->varp.string, pref->saved_val.string) != 0) {
-      *pref_changed_p = TRUE;
-      g_free((void *)*pref->varp.string);
-      *pref->varp.string = g_strdup(pref->saved_val.string);
-    }
-    break;
+  gboolean *must_redissect_p = (gboolean *)user_data;
+  pref_unstash_data_t unstashed_data;
 
-  case PREF_RANGE:
-    if (!ranges_are_equal(*pref->varp.range, pref->saved_val.range)) {
-      *pref_changed_p = TRUE;
-      g_free(*pref->varp.range);
-      *pref->varp.range = range_copy(pref->saved_val.range);
-    }
-    break;
-
-  case PREF_STATIC_TEXT:
-  case PREF_UAT:
-    break;
-
-  case PREF_OBSOLETE:
-    g_assert_not_reached();
-    break;
+  /* Ignore any preferences with their own interface */
+  if (!module->use_gui) {
+      return 0;
   }
-  return 0;
-}
-
-static guint
-module_prefs_revert(module_t *module, gpointer user_data)
-{
-  gboolean *must_redissect_p = user_data;
 
   /* For all preferences in this module, revert its value to the value
      it had when we popped up the Preferences dialog.  Find out whether
      this changes any of them. */
   module->prefs_changed = FALSE;        /* assume none of them changed */
-  prefs_pref_foreach(module, pref_revert, &module->prefs_changed);
+  unstashed_data.module = module;
+  unstashed_data.handle_decode_as = FALSE;
+  prefs_pref_foreach(module, pref_unstash, &unstashed_data);
 
   /* If any of them changed, indicate that we must redissect and refilter
      the current capture (if we have one), as the preference change
@@ -1629,21 +1591,20 @@ prefs_main_cancel_cb(GtkWidget *cancel_bt _U_, gpointer parent_w)
 
   /* Free up the current preferences and copy the saved preferences to the
      current preferences. */
-  free_prefs(&prefs);
-  copy_prefs(&prefs, &saved_prefs);
-  cfile.cinfo.columns_changed = FALSE; /* [XXX: "columns_changed" should treally be stored in prefs struct ??] */
+  cfile.columns_changed = FALSE; /* [XXX: "columns_changed" should treally be stored in prefs struct ??] */
 
   /* Now revert the registered preferences. */
   prefs_modules_foreach(module_prefs_revert, &must_redissect);
 
   /* Now apply the reverted-to preferences. */
-  prefs_main_apply_all(parent_w, must_redissect);
+  prefs_main_apply_all((GtkWidget *)parent_w, must_redissect);
 
   window_destroy(GTK_WIDGET(parent_w));
 
   if (must_redissect) {
     /* Redissect all the packets, and re-evaluate the display filter. */
     redissect_packets();
+    redissect_all_packet_windows();
   }
 }
 
@@ -1661,7 +1622,7 @@ prefs_main_delete_event_cb(GtkWidget *prefs_w_lcl, GdkEvent *event _U_,
 static void
 prefs_main_destroy_cb(GtkWidget *win _U_, gpointer parent_w)
 {
-  prefs_main_destroy_all(parent_w);
+  prefs_main_destroy_all((GtkWidget *)parent_w);
 
   /* Note that we no longer have a "Preferences" dialog box. */
   prefs_w = NULL;
@@ -1669,7 +1630,7 @@ prefs_main_destroy_cb(GtkWidget *win _U_, gpointer parent_w)
 
 struct properties_data {
   const char *title;
-  module_t *module;
+  module_t   *module;
 };
 
 static guint
@@ -1677,13 +1638,20 @@ module_search_properties(module_t *module, gpointer user_data)
 {
   struct properties_data *p = (struct properties_data *)user_data;
 
+  if (!module->use_gui) {
+      /* This module uses its own GUI interface, so its not a part
+       * of this search
+       */
+      return 0;
+  }
+
   /* If this module has the specified title, remember it. */
   if (strcmp(module->title, p->title) == 0) {
     p->module = module;
     return 1;   /* stops the search */
   }
 
-  if(prefs_module_has_submodules(module))
+  if (prefs_module_has_submodules(module))
     return prefs_modules_foreach_submodules(module, module_search_properties, p);
 
   return 0;
@@ -1692,11 +1660,11 @@ module_search_properties(module_t *module, gpointer user_data)
 static void
 tree_expand_row(GtkTreeModel *model, GtkTreeView *tree_view, GtkTreeIter *iter)
 {
-  GtkTreeIter   parent;
-  GtkTreePath   *path;
+  GtkTreeIter  parent;
+  GtkTreePath *path;
 
   /* expand the parent first */
-  if(gtk_tree_model_iter_parent(model, &parent, iter))
+  if (gtk_tree_model_iter_parent(model, &parent, iter))
     tree_expand_row(model, tree_view, &parent);
 
   path = gtk_tree_model_get_path(model, iter);
@@ -1712,8 +1680,8 @@ tree_expand_row(GtkTreeModel *model, GtkTreeView *tree_view, GtkTreeIter *iter)
 static void
 tree_select_node(GtkWidget *tree, prefs_tree_iter *iter)
 {
-  GtkTreeIter  local_iter = *iter;
-  GtkTreeView  *tree_view = GTK_TREE_VIEW(tree);
+  GtkTreeIter   local_iter = *iter;
+  GtkTreeView  *tree_view  = GTK_TREE_VIEW(tree);
   GtkTreeModel *model;
   GtkTreePath  *first_path;
 
@@ -1742,25 +1710,52 @@ tree_select_node(GtkWidget *tree, prefs_tree_iter *iter)
 void
 properties_cb(GtkWidget *w, gpointer dummy)
 {
-  header_field_info *hfinfo;
-  const gchar *title;
-  struct properties_data p;
-  int page_num;
-  GtkWidget *sw;
-  GtkWidget *frame;
-  module_t *page_module;
+  header_field_info      *hfinfo;
+  const gchar            *title = NULL;
+  struct properties_data  p;
+  int                     page_num;
+  GtkWidget              *sw;
+  GtkWidget              *frame;
+  module_t               *page_module;
 
   if (cfile.finfo_selected == NULL) {
-    /* There is no field selected */
-    return;
+    const gchar *abbrev;
+
+    /* There is no field selected, try use on top protocol */
+    if (cfile.edt && cfile.edt->tree) {
+        GPtrArray          *ga;
+        field_info         *v;
+        guint              i;
+
+        ga = proto_all_finfos(cfile.edt->tree);
+
+        for (i = ga->len - 1; i > 0 ; i -= 1) {
+
+            v = (field_info *)g_ptr_array_index (ga, i);
+            hfinfo =  v->hfinfo;
+
+            if (!g_str_has_prefix(hfinfo->abbrev, "text") &&
+                    !g_str_has_prefix(hfinfo->abbrev, "_ws.expert") &&
+                    !g_str_has_prefix(hfinfo->abbrev, "_ws.malformed")) {
+                if (hfinfo->parent == -1) {
+                    abbrev = hfinfo->abbrev;
+                } else {
+                    abbrev = proto_registrar_get_abbrev(hfinfo->parent);
+                }
+                title = prefs_get_title_by_name(abbrev);
+                break;
+            }
+        }
+    }
+  } else {
+    /* Find the title for the protocol for the selected field. */
+    hfinfo = cfile.finfo_selected->hfinfo;
+    if (hfinfo->parent == -1)
+        title = prefs_get_title_by_name(hfinfo->abbrev);
+    else
+        title = prefs_get_title_by_name(proto_registrar_get_abbrev(hfinfo->parent));
   }
 
-  /* Find the title for the protocol for the selected field. */
-  hfinfo = cfile.finfo_selected->hfinfo;
-  if (hfinfo->parent == -1)
-    title = prefs_get_title_by_name(hfinfo->abbrev);
-  else
-    title = prefs_get_title_by_name(proto_registrar_get_abbrev(hfinfo->parent));
   if (!title)
     return;     /* Couldn't find it. XXX - just crash? "Can't happen"? */
 
@@ -1785,18 +1780,18 @@ properties_cb(GtkWidget *w, gpointer dummy)
   /* Search all the pages in that window for the one with the specified
      module. */
   for (page_num = 0;
-       (sw = gtk_notebook_get_nth_page(g_object_get_data(G_OBJECT(prefs_w), E_PREFSW_NOTEBOOK_KEY), page_num)) != NULL;
+       (sw = gtk_notebook_get_nth_page((GtkNotebook *)g_object_get_data(G_OBJECT(prefs_w), E_PREFSW_NOTEBOOK_KEY), page_num)) != NULL;
        page_num++) {
     /* Get the frame from the scrollable window */
-    frame = g_object_get_data(G_OBJECT(sw), E_PAGESW_FRAME_KEY);
+    frame = (GtkWidget *)g_object_get_data(G_OBJECT(sw), E_PAGESW_FRAME_KEY);
     /* Get the module for this page (non-protocol prefs don't have one). */
-    if(frame) {
-      page_module = g_object_get_data(G_OBJECT(frame), E_PAGE_MODULE_KEY);
+    if (frame) {
+      page_module = (module_t *)g_object_get_data(G_OBJECT(frame), E_PAGE_MODULE_KEY);
       if (page_module != NULL) {
         if (page_module == p.module) {
           tree_select_node(
-            g_object_get_data(G_OBJECT(prefs_w), E_PREFSW_TREE_KEY),
-            g_object_get_data(G_OBJECT(frame), E_PAGE_ITER_KEY));
+            (GtkWidget *)g_object_get_data(G_OBJECT(prefs_w), E_PREFSW_TREE_KEY),
+            (GtkTreeIter *)g_object_get_data(G_OBJECT(frame), E_PAGE_ITER_KEY));
           return;
         }
       }
@@ -1809,7 +1804,7 @@ properties_cb(GtkWidget *w, gpointer dummy)
 static void
 prefs_tree_select_cb(GtkTreeSelection *sel, gpointer dummy _U_)
 {
-  gint page;
+  gint          page;
   GtkTreeModel *model;
   GtkTreeIter   iter;
 
@@ -1817,11 +1812,12 @@ prefs_tree_select_cb(GtkTreeSelection *sel, gpointer dummy _U_)
   {
     gtk_tree_model_get(model, &iter, 1, &page, -1);
     if (page >= 0)
-      gtk_notebook_set_current_page(g_object_get_data(G_OBJECT(prefs_w), E_PREFSW_NOTEBOOK_KEY), page);
+      gtk_notebook_set_current_page((GtkNotebook *)g_object_get_data(G_OBJECT(prefs_w), E_PREFSW_NOTEBOOK_KEY), page);
   }
 }
 
 
+
 /*
  * Editor modelines
  *