GTK: Wrap static preference labels.
[metze/wireshark/wip.git] / ui / gtk / prefs_dlg.c
index 54fbe51039226707f4ad66cad75d6cb5a35eace6..0437a2b4f81ee0603f90a52804f41149ad6f52d1 100644 (file)
@@ -1,8 +1,6 @@
 /* prefs_dlg.c
  * Routines for handling preferences
  *
 /* prefs_dlg.c
  * Routines for handling preferences
  *
- * $Id$
- *
  * Wireshark - Network traffic analyzer
  * By Gerald Combs <gerald@wireshark.org>
  * Copyright 1998 Gerald Combs
  * Wireshark - Network traffic analyzer
  * By Gerald Combs <gerald@wireshark.org>
  * Copyright 1998 Gerald Combs
 
 #include <gtk/gtk.h>
 
 
 #include <gtk/gtk.h>
 
+#include <stdlib.h>
 #include <string.h>
 
 #include <epan/packet.h>
 #include <epan/prefs.h>
 #include <string.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/prefs-int.h>
 #include <epan/epan_dissect.h>
+#include <epan/decode_as.h>
 
 
-#include "../file.h"
-#include "../print.h"
 #include "ui/preference_utils.h"
 #include "ui/preference_utils.h"
-#include "ui/simple_dialog.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/main.h"
 #include "ui/gtk/prefs_column.h"
 #include "ui/gtk/prefs_dlg.h"
 #include "ui/gtk/help_dlg.h"
 #include "ui/gtk/keys.h"
 #include "ui/gtk/uat_gui.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/file_dlg.h"
-#include "ui/gtk/dlg_utils.h"
 #include "ui/gtk/packet_win.h"
 #include "ui/gtk/packet_win.h"
+#include "simple_dialog.h"
 
 #ifdef HAVE_LIBPCAP
 #ifdef _WIN32
 
 #ifdef HAVE_LIBPCAP
 #ifdef _WIN32
-#include "capture-wpcap.h"
+#include <caputils/capture-wpcap.h>
 #endif /* _WIN32 */
 #ifdef HAVE_AIRPCAP
 #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
 #include "airpcap_gui_utils.h"
 #endif
 #endif
@@ -131,20 +127,20 @@ pref_show(pref_t *pref, gpointer user_data)
   const char *type_name = prefs_pref_type_name(pref);
   char       *label_string;
   size_t      label_len;
   const char *type_name = prefs_pref_type_name(pref);
   char       *label_string;
   size_t      label_len;
-  char        uint_str[10+1];
+  char       *uint_str;
   char *tooltip_txt;
 
   /* Give this preference a label which is its title, followed by a colon,
      and left-align it. */
   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 = (char *)g_malloc(label_len);
   g_strlcpy(label_string, title, label_len);
 
   label_len = strlen(title) + 2;
   label_string = (char *)g_malloc(label_len);
   g_strlcpy(label_string, title, label_len);
 
-  tooltip_txt = pref->description? g_strdup_printf("%s\n\nName: %s.%s\nType: %s",
-                                                   pref->description,
+  tooltip_txt = prefs_get_description(pref) ? g_strdup_printf("%s\n\nName: %s.%s\nType: %s",
+                                                   prefs_get_description(pref),
                                                    module->name,
                                                    module->name,
-                                                   pref->name,
+                                                   prefs_get_name(pref),
                                                    type_name ? type_name : "Unknown"
                                                    ): NULL;
 
                                                    type_name ? type_name : "Unknown"
                                                    ): NULL;
 
@@ -152,7 +148,7 @@ pref_show(pref_t *pref, gpointer user_data)
    * 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.
    */
    * 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);
     g_strlcat(label_string, ":", label_len);
 
   pref_stash(pref, NULL);
@@ -160,97 +156,89 @@ pref_show(pref_t *pref, gpointer user_data)
   /* 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. */
   /* 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:
 
   case PREF_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. */
     /* 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->stashed_val.uint);
-      break;
-
-    case 8:
-      g_snprintf(uint_str, sizeof(uint_str), "%o", pref->stashed_val.uint);
-      break;
-
-    case 16:
-      g_snprintf(uint_str, sizeof(uint_str), "%x", pref->stashed_val.uint);
-      break;
-    }
-    pref->control = create_preference_entry(main_grid, pref->ordinal,
+    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,
                                             label_string, tooltip_txt,
-                                            uint_str);
+                                            uint_str));
+    g_free(uint_str);
     break;
 
   case PREF_BOOL:
     break;
 
   case PREF_BOOL:
-    pref->control = create_preference_check_button(main_grid, pref->ordinal,
+    prefs_set_control(pref, create_preference_check_button(main_grid, prefs_get_ordinal(pref),
                                                    label_string, tooltip_txt,
                                                    label_string, tooltip_txt,
-                                                   pref->stashed_val.boolval);
+                                                   prefs_get_bool_value(pref, pref_stashed)));
     break;
 
   case PREF_ENUM:
     break;
 
   case PREF_ENUM:
-    if (pref->info.enum_info.radio_buttons) {
+    if (prefs_get_enum_radiobuttons(pref)) {
       /* Show it as radio buttons. */
       /* Show it as radio buttons. */
-      pref->control = create_preference_radio_buttons(main_grid, pref->ordinal,
+      prefs_set_control(pref, create_preference_radio_buttons(main_grid, prefs_get_ordinal(pref),
                                                       label_string, tooltip_txt,
                                                       label_string, tooltip_txt,
-                                                      pref->info.enum_info.enumvals,
-                                                      pref->stashed_val.enumval);
+                                                      prefs_get_enumvals(pref),
+                                                      prefs_get_enum_value(pref, pref_stashed)));
     } else {
       /* Show it as an option menu. */
     } else {
       /* Show it as an option menu. */
-      pref->control = create_preference_option_menu(main_grid, pref->ordinal,
+      prefs_set_control(pref, create_preference_option_menu(main_grid, prefs_get_ordinal(pref),
                                                     label_string, tooltip_txt,
                                                     label_string, tooltip_txt,
-                                                    pref->info.enum_info.enumvals,
-                                                    pref->stashed_val.enumval);
+                                                    prefs_get_enumvals(pref),
+                                                    prefs_get_enum_value(pref, pref_stashed)));
     }
     break;
 
   case PREF_STRING:
     }
     break;
 
   case PREF_STRING:
-    pref->control = create_preference_entry(main_grid, pref->ordinal,
+    prefs_set_control(pref, create_preference_entry(main_grid, prefs_get_ordinal(pref),
                                             label_string, tooltip_txt,
                                             label_string, tooltip_txt,
-                                            pref->stashed_val.string);
+                                            prefs_get_string_value(pref, pref_stashed)));
     break;
 
   case PREF_FILENAME:
     break;
 
   case PREF_FILENAME:
-    pref->control = create_preference_path_entry(main_grid, pref->ordinal,
+    prefs_set_control(pref, create_preference_path_entry(main_grid, prefs_get_ordinal(pref),
                                                      label_string,
                                                      tooltip_txt,
                                                      label_string,
                                                      tooltip_txt,
-                                                     pref->stashed_val.string, FALSE);
+                                                     prefs_get_string_value(pref, pref_stashed), FALSE));
     break;
 
   case PREF_DIRNAME:
     break;
 
   case PREF_DIRNAME:
-    pref->control = create_preference_path_entry(main_grid, pref->ordinal,
+    prefs_set_control(pref, create_preference_path_entry(main_grid, prefs_get_ordinal(pref),
                                                      label_string,
                                                      tooltip_txt,
                                                      label_string,
                                                      tooltip_txt,
-                                                     pref->stashed_val.string, TRUE);
+                                                     prefs_get_string_value(pref, pref_stashed), TRUE));
     break;
 
   case PREF_RANGE:
     break;
 
   case PREF_RANGE:
+  case PREF_DECODE_AS_RANGE:
   {
     char *range_str_p;
 
   {
     char *range_str_p;
 
-    range_str_p = range_convert_range(*pref->varp.range);
-    pref->control = create_preference_entry(main_grid, pref->ordinal,
+    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,
                                             label_string, tooltip_txt,
-                                            range_str_p);
+                                            range_str_p));
+    wmem_free(NULL, range_str_p);
     break;
   }
 
   case PREF_STATIC_TEXT:
   {
     break;
   }
 
   case PREF_STATIC_TEXT:
   {
-    pref->control = create_preference_static_text(main_grid, pref->ordinal,
-                                                  label_string, tooltip_txt);
+    prefs_set_control(pref, create_preference_static_text(main_grid, prefs_get_ordinal(pref),
+                                                  label_string, tooltip_txt));
     break;
   }
 
   case PREF_UAT:
   {
     break;
   }
 
   case PREF_UAT:
   {
-    pref->control = create_preference_uat(main_grid, pref->ordinal,
-                                          label_string, tooltip_txt,
-                                          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;
   }
 
     break;
   }
 
@@ -883,7 +871,7 @@ create_preference_path_entry(GtkWidget *main_grid, int grid_position,
   ws_gtk_grid_attach_defaults(GTK_GRID(main_grid), file_bt_hb, 1, grid_position, 1, 1);
   gtk_widget_show(file_bt_hb);
 
   ws_gtk_grid_attach_defaults(GTK_GRID(main_grid), file_bt_hb, 1, grid_position, 1, 1);
   gtk_widget_show(file_bt_hb);
 
-  button = gtk_button_new_from_stock(WIRESHARK_STOCK_BROWSE);
+  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);
 
   gtk_box_pack_end(GTK_BOX(file_bt_hb), button, FALSE, FALSE, 0);
   gtk_widget_show(button);
 
@@ -910,10 +898,13 @@ create_preference_static_text(GtkWidget *main_grid, int grid_position,
 {
   GtkWidget *label;
 
 {
   GtkWidget *label;
 
-  if (label_text != NULL)
+  if (label_text != NULL) {
     label = gtk_label_new(label_text);
     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("");
     label = gtk_label_new("");
+  }
   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);
   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);
@@ -930,7 +921,7 @@ create_preference_uat(GtkWidget *main_grid, int grid_position,
 
   set_option_label(main_grid, grid_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);
 
 
   g_signal_connect(button, "clicked", G_CALLBACK(uat_window_cb), uat);
 
@@ -951,10 +942,11 @@ pref_check(pref_t *pref, gpointer user_data)
   pref_t     **badpref = (pref_t **)user_data;
 
   /* Fetch the value of the preference, and check whether it's valid. */
   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:
 
   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
     errno = 0;
 
     /* XXX: The following ugly hack prevents a gcc warning
@@ -970,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."
        ]
     */
          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 */
     if (p == str_val || *p != '\0' || errno != 0) {
       *badpref = pref;
       return PREFS_SET_SYNTAX_ERR;      /* number was bad */
@@ -992,16 +984,18 @@ pref_check(pref_t *pref, gpointer user_data)
     break;
 
   case PREF_RANGE:
     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 (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;
         *badpref = pref;
+        wmem_free(NULL, newrange);
         return PREFS_SET_SYNTAX_ERR;    /* range was bad */
       }
         return PREFS_SET_SYNTAX_ERR;    /* range was bad */
       }
-      g_free(newrange);
+      wmem_free(NULL, newrange);
     }
     break;
 
     }
     break;
 
@@ -1039,85 +1033,90 @@ pref_fetch(pref_t *pref, gpointer user_data)
 {
   const char *str_val;
   char       *p;
 {
   const char *str_val;
   char       *p;
-  guint       uval;
+  guint       uval, uval_stashed;
   gboolean    bval;
   gint        enumval;
   gboolean    bval;
   gint        enumval;
-  gboolean   *pref_changed_p = (gboolean *)user_data;
+  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. */
 
   /* 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:
 
   case PREF_UINT:
-    str_val = gtk_entry_get_text(GTK_ENTRY(pref->control));
-    uval = (guint)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 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:
     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:
     break;
 
   case PREF_ENUM:
-    if (pref->info.enum_info.radio_buttons) {
-      enumval = fetch_preference_radio_buttons_val((GtkWidget *)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 {
     } else {
-      enumval = fetch_preference_option_menu_val((GtkWidget *)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:
   case PREF_FILENAME:
   case PREF_DIRNAME:
     break;
 
   case PREF_STRING:
   case PREF_FILENAME:
   case PREF_DIRNAME:
-    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);
-    }
+    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;
 
     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 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;
     break;
-  }
 
   case PREF_STATIC_TEXT:
   case PREF_UAT:
 
   case PREF_STATIC_TEXT:
   case PREF_UAT:
@@ -1147,7 +1146,7 @@ module_prefs_fetch(module_t *module, gpointer user_data)
   /* 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 */
   /* 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
 
   /* If any of them changed, indicate that we must redissect and refilter
      the current capture (if we have one), as the preference change
@@ -1252,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)) {
 
   /* 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_UINT:
+    case PREF_DECODE_AS_UINT:
       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
                     "The value for \"%s\" isn't a valid number.",
       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:
       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.",
       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:
       return FALSE;
 
     default:
@@ -1391,6 +1392,62 @@ static void prefs_copy(void) {
   prefs_modules_foreach(module_prefs_copy, NULL);
 }
 
   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;
+
+  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)
+{
+  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 {
+    prefs_main_write();
+
+    if (save_decode_as_entries(&err) < 0)
+    {
+        simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", err);
+        g_free(err);
+    }
+  }
+}
+
 static void
 prefs_main_ok_cb(GtkWidget *ok_bt _U_, gpointer parent_w)
 {
 static void
 prefs_main_ok_cb(GtkWidget *ok_bt _U_, gpointer parent_w)
 {
@@ -1401,7 +1458,7 @@ prefs_main_ok_cb(GtkWidget *ok_bt _U_, gpointer parent_w)
 
   /* if we don't have a Save button, just save the settings now */
   if (!prefs.gui_use_pref_save) {
 
   /* 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);
   }
 
 #ifdef HAVE_AIRPCAP
   }
 
 #ifdef HAVE_AIRPCAP
@@ -1409,7 +1466,7 @@ prefs_main_ok_cb(GtkWidget *ok_bt _U_, gpointer parent_w)
    * Load the Wireshark decryption keys (just set) and save
    * the changes to the adapters' registry
    */
    * Load the Wireshark decryption keys (just set) and save
    * the changes to the adapters' registry
    */
-  airpcap_load_decryption_keys(airpcap_if_list);
+  airpcap_load_decryption_keys(g_airpcap_if_list);
 #endif
 
   prefs_main_apply_all((GtkWidget *)parent_w, must_redissect);
 #endif
 
   prefs_main_apply_all((GtkWidget *)parent_w, must_redissect);
@@ -1442,7 +1499,7 @@ prefs_main_apply_cb(GtkWidget *apply_bt _U_, gpointer parent_w)
 
   /* if we don't have a Save button, just save the settings now */
   if (!prefs.gui_use_pref_save) {
 
   /* 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_copy();     /* save prefs for reverting if Cancel */
   }
 
@@ -1470,7 +1527,7 @@ prefs_main_save_cb(GtkWidget *save_bt _U_, gpointer parent_w)
   if (!prefs_main_fetch_all((GtkWidget *)parent_w, &must_redissect))
     return; /* Errors in some preference setting - already reported */
 
   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.
   prefs_copy();     /* save prefs for reverting if Cancel */
 
   /* Now apply those preferences.
@@ -1503,6 +1560,7 @@ static guint
 module_prefs_revert(module_t *module, gpointer user_data)
 {
   gboolean *must_redissect_p = (gboolean *)user_data;
 module_prefs_revert(module_t *module, gpointer user_data)
 {
   gboolean *must_redissect_p = (gboolean *)user_data;
+  pref_unstash_data_t unstashed_data;
 
   /* Ignore any preferences with their own interface */
   if (!module->use_gui) {
 
   /* Ignore any preferences with their own interface */
   if (!module->use_gui) {
@@ -1513,7 +1571,9 @@ module_prefs_revert(module_t *module, gpointer user_data)
      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 */
      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_unstash, &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
 
   /* If any of them changed, indicate that we must redissect and refilter
      the current capture (if we have one), as the preference change
@@ -1675,8 +1735,8 @@ properties_cb(GtkWidget *w, gpointer dummy)
             hfinfo =  v->hfinfo;
 
             if (!g_str_has_prefix(hfinfo->abbrev, "text") &&
             hfinfo =  v->hfinfo;
 
             if (!g_str_has_prefix(hfinfo->abbrev, "text") &&
-                    !g_str_has_prefix(hfinfo->abbrev, "expert") &&
-                    !g_str_has_prefix(hfinfo->abbrev, "malformed")) {
+                    !g_str_has_prefix(hfinfo->abbrev, "_ws.expert") &&
+                    !g_str_has_prefix(hfinfo->abbrev, "_ws.malformed")) {
                 if (hfinfo->parent == -1) {
                     abbrev = hfinfo->abbrev;
                 } else {
                 if (hfinfo->parent == -1) {
                     abbrev = hfinfo->abbrev;
                 } else {