Removed unused argument to new_packet_list_copy_summary_cb().
[obnox/wireshark/wip.git] / gtk / decode_as_dlg.c
index d403fc887b7fbddfc5369161145d7f0e4e5b57b7..dfe3d559e3e1126eb18a000965af9b3d9fd53cd6 100644 (file)
@@ -1,6 +1,6 @@
 /* decode_as_dlg.c
  *
- * $Id: decode_as_dlg.c,v 1.31 2003/03/01 13:08:59 deniel Exp $
+ * $Id$
  *
  * Routines to modify dissector tables on the fly.
  *
 #ifdef HAVE_CONFIG_H
 # include "config.h"
 #endif
+#include <string.h>
 
 #include <gtk/gtk.h>
-#include <string.h>
+#include <gdk/gdkkeysyms.h>
+#if GTK_CHECK_VERSION(3,0,0)
+# include <gdk/gdkkeysyms-compat.h>
+#endif
 
-#include "decode_as_dlg.h"
-#include "dlg_utils.h"
-#include "globals.h"
-#include "simple_dialog.h"
 #include <epan/packet.h>
-#include "ipproto.h"
-#include "ui_util.h"
 #include <epan/epan_dissect.h>
-#include "compat_macros.h"
+
+#include "../simple_dialog.h"
+
+#include "gtk/main.h"
+#include "gtk/decode_as_dlg.h"
+#include "gtk/dlg_utils.h"
+#include "gtk/gui_utils.h"
+#include "gtk/decode_as_dcerpc.h"
+#include "gtk/decode_as_ber.h"
+#include "gtk/help_dlg.h"
+#include "utf8_entities.h"
 
 #undef DEBUG
 
 /**************************************************/
 
 /*
- * Enum used to track which radio button is currently selected in the
- * dialog. These buttons are labeled "Decode" and "Do not decode".
- */
-enum action_type {
-    /* The "Decode" button is currently selected. */
-    E_DECODE_YES,
-
-    /* The "Do not decode" button is currently selected. */
-    E_DECODE_NO
-};
-
-/*
- * Enum used to track which transport layer port menu item is
+ * Enum used to track which transport layer port combo_box item is
  * currently selected in the dialog.  These items are labeled "source",
  * "destination", and "source/destination".
  */
 enum srcdst_type {
-    /* The "source port" menu item is currently selected. */
+    /* The "source port" combo_box item is currently selected. */
     E_DECODE_SPORT,
-    /* The "destination port" menu item is currently selected. */
+    /* The "destination port" combo_box item is currently selected. */
     E_DECODE_DPORT,
-    /* The "source/destination port" menu item is currently selected. */
-    E_DECODE_BPORT
+    /* The "source/destination port" combo_box item is currently selected. */
+    E_DECODE_BPORT,
+    /* For SCTP only. This MUST be the last entry! */
+    E_DECODE_PPID
 };
 
-#define E_DECODE_MIN_HEIGHT 100
+#define E_DECODE_MIN_HEIGHT 300
 #define E_NOTEBOOK "notebook"
 
-#define E_MENU_SRCDST "menu_src_dst"
+#define E_COMBO_BOX_SRCDST "combo_box_src_dst"
 
-#define E_PAGE_ACTION "notebook_page_action"
-#define E_PAGE_LIST   "notebook_page_list"
-#define E_PAGE_TABLE  "notebook_page_table_name"
-#define E_PAGE_TITLE  "notebook_page_title"
-#define E_PAGE_VALUE  "notebook_page_value"
+#define E_PAGE_DPORT "dport"
+#define E_PAGE_SPORT "sport"
+#define E_PAGE_PPID  "ppid"
+#define E_PAGE_ASN1  "asn1"
 
-/*
- * Columns for a "Select" list.
- * Note that most of these columns aren't displayed; they're attached
- * to the row of the table as additional information.
- */
-#define E_LIST_S_PROTO_NAME 0
-#define E_LIST_S_TABLE     1
-/* The following is for debugging in decode_add_to_list */
-#define E_LIST_S_MAX       E_LIST_S_TABLE
-#define E_LIST_S_COLUMNS   (E_LIST_S_MAX + 1)
 
 /*
  * Columns for a "Display" list
  */
-#define E_LIST_D_TABLE     0
-#define E_LIST_D_PORT      1
+#define E_LIST_D_TABLE      0
+#define E_LIST_D_SELECTOR   1
 #define E_LIST_D_INITIAL    2
 #define E_LIST_D_CURRENT    3
-#define E_LIST_D_MAX       E_LIST_D_CURRENT
+#define E_LIST_D_MAX        E_LIST_D_CURRENT
 #define E_LIST_D_COLUMNS   (E_LIST_D_MAX + 1)
 
 /**************************************************/
@@ -118,7 +105,7 @@ static GtkWidget *decode_w = NULL;
 /*
  * A static pointer to the current "Decode As:Show" window.  This is
  * kept so that if somebody tries to do clock the "Show Current"
- * button or slect the "Display:User Specified Decodes" menu item
+ * button or select the "Display:User Specified Decodes" menu item
  * while there's already a "Decode As:Show" window up, we just pop up
  * the existing one, rather than creating a new one.
  */
@@ -129,7 +116,7 @@ static GtkWidget *decode_show_w = NULL;
  * selected the "Decode" radio button.  When the "Do not decode"
  * button is selected these items should be dimmed.
  */
-static GSList *decode_dimmable = NULL;
+GSList *decode_dimmable = NULL;
 
 /*
  * Remember the "action" radio button that is currently selected in
@@ -137,10 +124,21 @@ static GSList *decode_dimmable = NULL;
  * modified in a callback routine, and read in the routine that
  * handles a click in the "OK" button for the dialog.
  */
-static enum action_type        requested_action = -1;
+enum action_type  requested_action = -1;
+
 
 /**************************************************/
-/*            Resett Changed Dissectors           */
+/*            Global Functions                    */
+/**************************************************/
+
+/* init this module */
+void decode_as_init(void) {
+
+    decode_dcerpc_init();
+}
+
+/**************************************************/
+/*            Reset Changed Dissectors            */
 /**************************************************/
 
 /*
@@ -151,8 +149,13 @@ static enum action_type    requested_action = -1;
 struct dissector_delete_item {
     /* The name of the dissector table */
     const gchar *ddi_table_name;
-    /* The port number in the dissector table */
-    guint   ddi_port;
+    /* The type of the selector in that dissector table */
+    ftenum_t ddi_selector_type;
+    /* The selector in the dissector table */
+    union {
+        guint   sel_uint;
+        char    *sel_string;
+    } ddi_selector;
 };
 
 /*
@@ -188,14 +191,32 @@ GSList *dissector_reset_list = NULL;
  * @param user_data Unused.
  */
 static void
-decode_build_reset_list (gchar *table_name, gpointer key,
-                        gpointer value _U_, gpointer user_data _U_)
+decode_build_reset_list (const gchar *table_name, ftenum_t selector_type,
+                         gpointer key, gpointer value _U_,
+                         gpointer user_data _U_)
 {
     dissector_delete_item_t *item;
 
     item = g_malloc(sizeof(dissector_delete_item_t));
     item->ddi_table_name = table_name;
-    item->ddi_port = GPOINTER_TO_UINT(key);
+    item->ddi_selector_type = selector_type;
+    switch (selector_type) {
+
+    case FT_UINT8:
+    case FT_UINT16:
+    case FT_UINT24:
+    case FT_UINT32:
+        item->ddi_selector.sel_uint = GPOINTER_TO_UINT(key);
+        break;
+
+    case FT_STRING:
+    case FT_STRINGZ:
+        item->ddi_selector.sel_string = key;
+        break;
+
+    default:
+        g_assert_not_reached();
+    }
     dissector_reset_list = g_slist_prepend(dissector_reset_list, item);
 }
 
@@ -204,6 +225,69 @@ decode_build_reset_list (gchar *table_name, gpointer key,
 /*             Show Changed Dissectors            */
 /**************************************************/
 
+#define SORT_ALPHABETICAL 0
+
+static gint
+sort_iter_compare_func (GtkTreeModel *model,
+                        GtkTreeIter *a,
+                        GtkTreeIter *b,
+                        gpointer user_data)
+{
+    gint sortcol = GPOINTER_TO_INT(user_data);
+    gint ret = 0;
+    switch (sortcol)
+    {
+        case SORT_ALPHABETICAL:
+        {
+        gchar *name1, *name2;
+        gtk_tree_model_get(model, a, 0, &name1, -1);
+        gtk_tree_model_get(model, b, 0, &name2, -1);
+        if (name1 == NULL || name2 == NULL)
+        {
+            if (name1 == NULL && name2 == NULL)
+                break; /* both equal => ret = 0 */
+            ret = (name1 == NULL) ? -1 : 1;
+        }
+        else
+        {
+            ret = g_ascii_strcasecmp(name1,name2);
+        }
+        g_free(name1);
+        g_free(name2);
+        }
+        break;
+        default:
+        g_return_val_if_reached(0);
+    }
+    return ret;
+}
+
+
+void
+decode_add_to_show_list (gpointer list_data,
+                         const gchar *table_name,
+                         gchar *selector_name,
+                         const gchar *initial_proto_name,
+                         const gchar *current_proto_name)
+{
+    const gchar     *text[E_LIST_D_COLUMNS];
+    GtkListStore *store;
+    GtkTreeIter   iter;
+
+    store = (GtkListStore *)list_data;
+
+    text[E_LIST_D_TABLE] = table_name;
+    text[E_LIST_D_SELECTOR] = selector_name;
+    text[E_LIST_D_INITIAL] = initial_proto_name;
+    text[E_LIST_D_CURRENT] = current_proto_name;
+    gtk_list_store_append(store, &iter);
+    gtk_list_store_set(store, &iter, E_LIST_D_TABLE, text[E_LIST_D_TABLE],
+                       E_LIST_D_SELECTOR, text[E_LIST_D_SELECTOR],
+                       E_LIST_D_INITIAL, text[E_LIST_D_INITIAL],
+                       E_LIST_D_CURRENT, text[E_LIST_D_CURRENT], -1);
+}
+
+
 /*
  * This routine creates one entry in the list of protocol dissector
  * that have been changed.  It is called by the g_hash_foreach routine
@@ -224,87 +308,130 @@ decode_build_reset_list (gchar *table_name, gpointer key,
  * should be stored.
  */
 static void
-decode_build_show_list (gchar *table_name, gpointer key,
-                       gpointer value, gpointer user_data)
+decode_build_show_list (const gchar *table_name, ftenum_t selector_type,
+                        gpointer key, gpointer value, gpointer user_data)
 {
-#if GTK_MAJOR_VERSION < 2
-    GtkCList  *clist;
-    gint       row;
-#else
-    GtkListStore *store;
-    GtkTreeIter   iter;
-#endif
     dissector_handle_t current, initial;
-    gchar     *current_proto_name, *initial_proto_name, *text[E_LIST_D_COLUMNS];
-    gchar      string1[20];
+    const gchar *current_proto_name, *initial_proto_name;
+    gchar       *selector_name;
+    gchar        string1[20];
 
     g_assert(user_data);
     g_assert(value);
 
-#if GTK_MAJOR_VERSION < 2
-    clist = (GtkCList *)user_data;
-#else
-    store = (GtkListStore *)user_data;
-#endif
     current = dtbl_entry_get_handle(value);
     if (current == NULL)
-       current_proto_name = "(none)";
+        current_proto_name = "(none)";
     else
-       current_proto_name = dissector_handle_get_short_name(current);
+        current_proto_name = dissector_handle_get_short_name(current);
     initial = dtbl_entry_get_initial_handle(value);
     if (initial == NULL)
-       initial_proto_name = "(none)";
+        initial_proto_name = "(none)";
     else
-       initial_proto_name = dissector_handle_get_short_name(initial);
+        initial_proto_name = dissector_handle_get_short_name(initial);
+
+    switch (selector_type) {
+
+    case FT_UINT8:
+    case FT_UINT16:
+    case FT_UINT24:
+    case FT_UINT32:
+        switch (get_dissector_table_base(table_name)) {
 
-    text[E_LIST_D_TABLE] = get_dissector_table_ui_name(table_name);
-    switch (get_dissector_table_base(table_name)) {
+        case BASE_DEC:
+            g_snprintf(string1, sizeof(string1), "%u", GPOINTER_TO_UINT(key));
+            break;
 
-    case BASE_DEC:
-       sprintf(string1, "%u", GPOINTER_TO_UINT(key));
-       break;
+        case BASE_HEX:
+            switch (get_dissector_table_selector_type(table_name)) {
 
-    case BASE_HEX:
-       switch (get_dissector_table_type(table_name)) {
+            case FT_UINT8:
+                g_snprintf(string1, sizeof(string1), "0x%02x", GPOINTER_TO_UINT(key));
+                break;
 
-       case FT_UINT8:
-           sprintf(string1, "0x%02x", GPOINTER_TO_UINT(key));
-           break;
+            case FT_UINT16:
+                g_snprintf(string1, sizeof(string1), "0x%04x", GPOINTER_TO_UINT(key));
+                break;
 
-       case FT_UINT16:
-           sprintf(string1, "0x%04x", GPOINTER_TO_UINT(key));
-           break;
+            case FT_UINT24:
+                g_snprintf(string1, sizeof(string1), "0x%06x", GPOINTER_TO_UINT(key));
+                break;
 
-       case FT_UINT24:
-           sprintf(string1, "0x%06x", GPOINTER_TO_UINT(key));
-           break;
+            case FT_UINT32:
+                g_snprintf(string1, sizeof(string1), "0x%08x", GPOINTER_TO_UINT(key));
+                break;
 
-       case FT_UINT32:
-           sprintf(string1, "0x%08x", GPOINTER_TO_UINT(key));
-           break;
+            default:
+                g_assert_not_reached();
+                break;
+            }
+            break;
+
+        case BASE_OCT:
+            g_snprintf(string1, sizeof(string1), "%#o", GPOINTER_TO_UINT(key));
+            break;
+        }
+        selector_name = string1;
+        break;
 
-       default:
-           g_assert_not_reached();
-           break;
-       }
-       break;
+    case FT_STRING:
+    case FT_STRINGZ:
+        selector_name = key;
+        break;
 
-    case BASE_OCT:
-       sprintf(string1, "%#o", GPOINTER_TO_UINT(key));
-       break;
+    default:
+        g_assert_not_reached();
+        selector_name = NULL;
+        break;
     }
-    text[E_LIST_D_PORT] = string1;
-    text[E_LIST_D_INITIAL] = initial_proto_name;
-    text[E_LIST_D_CURRENT] = current_proto_name;
-#if GTK_MAJOR_VERSION < 2
-    row = gtk_clist_prepend(clist, text);
-#else
-    gtk_list_store_append(store, &iter);
-    gtk_list_store_set(store, &iter, E_LIST_D_TABLE, text[E_LIST_D_TABLE],
-                       E_LIST_D_PORT, text[E_LIST_D_PORT],
-                       E_LIST_D_INITIAL, text[E_LIST_D_INITIAL],
-                       E_LIST_D_CURRENT, text[E_LIST_D_CURRENT], -1);
-#endif
+
+    decode_add_to_show_list (
+        user_data,
+        get_dissector_table_ui_name(table_name),
+        selector_name,
+        initial_proto_name,
+        current_proto_name);
+}
+
+
+/* clear all settings */
+static void
+decode_clear_all(void)
+{
+    dissector_delete_item_t *item;
+    GSList *tmp;
+
+    dissector_all_tables_foreach_changed(decode_build_reset_list, NULL);
+
+    for (tmp = dissector_reset_list; tmp; tmp = g_slist_next(tmp)) {
+        item = tmp->data;
+        switch (item->ddi_selector_type) {
+
+        case FT_UINT8:
+        case FT_UINT16:
+        case FT_UINT24:
+        case FT_UINT32:
+            dissector_reset_uint(item->ddi_table_name,
+                                 item->ddi_selector.sel_uint);
+            break;
+
+        case FT_STRING:
+        case FT_STRINGZ:
+            dissector_reset_string(item->ddi_table_name,
+                                   item->ddi_selector.sel_string);
+            break;
+
+        default:
+            g_assert_not_reached();
+        }
+        g_free(item);
+    }
+    g_slist_free(dissector_reset_list);
+    dissector_reset_list = NULL;
+
+    decode_dcerpc_reset_all();
+
+    redissect_packets();
 }
 
 
@@ -313,61 +440,49 @@ decode_build_show_list (gchar *table_name, gpointer key,
  * the "Decode As:Show..." dialog window.  This routine destroys the
  * dialog box and performs other housekeeping functions.
  *
- * @param GtkWidget * A pointer to the "OK" button.
+ * @param ok_bt A pointer to the "OK" button.
  *
- * @param gpointer A pointer to the dialog window.
+ * @param parent_w A pointer to the dialog window.
  */
 static void
 decode_show_ok_cb (GtkWidget *ok_bt _U_, gpointer parent_w)
 {
-    gtk_widget_destroy(GTK_WIDGET(parent_w));
+    window_destroy(GTK_WIDGET(parent_w));
 }
 
 
 /*
- * This routine is called when the user clicks the "Reset" button in
+ * This routine is called when the user clicks the "Clear" button in
  * the "Decode As:Show..." dialog window.  This routine resets all the
  * dissector values and then destroys the dialog box and performs
  * other housekeeping functions.
  *
- * @param GtkWidget * A pointer to the "Reset" button.
+ * @param clear_bt A pointer to the "Clear" button.
  *
- * @param gpointer A pointer to the dialog window.
+ * @param parent_w A pointer to the dialog window.
  */
 static void
-decode_show_reset_cb (GtkWidget *reset_bt _U_, gpointer parent_w)
+decode_show_clear_cb (GtkWidget *clear_bt _U_, gpointer parent_w)
 {
-    dissector_delete_item_t *item;
-    GSList *tmp;
+    decode_clear_all();
 
-    dissector_all_tables_foreach_changed(decode_build_reset_list, NULL);
-
-    for (tmp = dissector_reset_list; tmp; tmp = g_slist_next(tmp)) {
-       item = tmp->data;
-       dissector_reset(item->ddi_table_name, item->ddi_port);
-       g_free(item);
-    }
-    g_slist_free(dissector_reset_list);
-    dissector_reset_list = NULL;
-
-    redissect_packets(&cfile);
-
-    gtk_widget_destroy(GTK_WIDGET(parent_w));
+    window_destroy(GTK_WIDGET(parent_w));
 }
 
 
 /*
- * This routine is called when the user clicks the "Close" button in
+ * This routine is called when the user clicks the X at the top right end in
  * the "Decode As:Show..." dialog window.  This routine simply calls the
- * cancel routine as if the user had clicked the cancel button instead
- * of the close button.
+ * ok routine as if the user had clicked the ok button.
  *
- * @param GtkWidget * A pointer to the dialog box.
+ * @param win       A pointer to the dialog box.
  *
- * @param gpointer Unknown
+ * @param event     A pointer to the event struct
+ *
+ * @param user_data Unused
  */
 static gboolean
-decode_show_delete_cb (GtkWidget *decode_w _U_, gpointer dummy _U_)
+decode_show_delete_cb (GtkWidget *win _U_, GdkEvent *event _U_, gpointer user_data _U_)
 {
     decode_show_ok_cb(NULL, decode_show_w);
     return FALSE;
@@ -380,9 +495,9 @@ decode_show_delete_cb (GtkWidget *decode_w _U_, gpointer dummy _U_)
  * the next time the user clicks the "Decode As:Show" button a new
  * dialog box will be created.
  *
- * @param GtkWidget * A pointer to the dialog box.
+ * @param win A pointer to the dialog box.
  *
- * @param gpointer Unknown
+ * @param user_data Unused
  */
 static void
 decode_show_destroy_cb (GtkWidget *win _U_, gpointer user_data _U_)
@@ -396,116 +511,98 @@ decode_show_destroy_cb (GtkWidget *win _U_, gpointer user_data _U_)
  * This routine creates the "Decode As:Show" dialog box. This dialog box
  * shows the user which protocols have had their dissectors changed.
  *
- * @param w Unknown
- * @param data Unknown
+ * @param w Unused
+ *
+ * @param user_data Unused
  */
 void
-decode_show_cb (GtkWidget * w _U_, gpointer data _U_)
+decode_show_cb (GtkWidget *w _U_, gpointer user_data _U_)
 {
-    GtkWidget         *main_vb, *bbox, *ok_bt, *button, *scrolled_window;
-    gchar             *titles[E_LIST_D_COLUMNS] = {
-        "Table", "Port", "Initial", "Current"
+    GtkWidget         *main_vb, *bbox, *ok_bt, *clear_bt, *help_bt, *scrolled_window;
+    const gchar       *titles[E_LIST_D_COLUMNS] = {
+        "Table", "Value", "Initial", "Current"
     };
     gint               column;
-#if GTK_MAJOR_VERSION < 2
-    GtkCList          *list;
-#else
     GtkListStore      *store;
     GtkTreeView       *list;
     GtkCellRenderer   *renderer;
     GtkTreeViewColumn *tc;
     GtkTreeIter        iter;
-#endif
 
     if (decode_show_w != NULL) {
-       /* There's already a "Decode As" dialog box; reactivate it. */
-       reactivate_window(decode_show_w);
-       return;
+        /* There's already a "Decode As" dialog box; reactivate it. */
+        reactivate_window(decode_show_w);
+        return;
     }
 
-    decode_show_w = dlg_window_new("Ethereal: Decode As: Show");
-    SIGNAL_CONNECT(decode_show_w, "delete_event", decode_show_delete_cb, NULL);
-    SIGNAL_CONNECT(decode_show_w, "destroy", decode_show_destroy_cb, NULL);
+    decode_show_w = dlg_window_new("Wireshark: Decode As: Show");
+    /* Provide a minimum of a couple of rows worth of data */
+    gtk_window_set_default_size(GTK_WINDOW(decode_show_w), -1, E_DECODE_MIN_HEIGHT);
 
     /* Container for each row of widgets */
     main_vb = gtk_vbox_new(FALSE, 2);
-    gtk_container_border_width(GTK_CONTAINER(main_vb), 5);
+    gtk_container_set_border_width(GTK_CONTAINER(main_vb), 5);
     gtk_container_add(GTK_CONTAINER(decode_show_w), main_vb);
 
-    {
-       /* Initialize list */
-#if GTK_MAJOR_VERSION < 2
-       list = GTK_CLIST(gtk_clist_new_with_titles(E_LIST_D_COLUMNS, titles));
-       gtk_clist_column_titles_passive(list);
-       for (column = 0; column < E_LIST_D_COLUMNS; column++)
-           gtk_clist_set_column_auto_resize(list, column, TRUE);
-       gtk_clist_set_selection_mode(list, GTK_SELECTION_EXTENDED);
-#else
-        store = gtk_list_store_new(E_LIST_D_COLUMNS, G_TYPE_STRING,
-                                   G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
-        list = GTK_TREE_VIEW(tree_view_new(GTK_TREE_MODEL(store)));
-        gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(list), TRUE);
-        gtk_tree_view_set_headers_clickable(GTK_TREE_VIEW(list), FALSE);
-       gtk_tree_selection_set_mode(gtk_tree_view_get_selection(list),
-                                    GTK_SELECTION_MULTIPLE);
-
-       for (column = 0; column < E_LIST_D_COLUMNS; column++) {
-            renderer = gtk_cell_renderer_text_new();
-            tc = gtk_tree_view_column_new_with_attributes(titles[column],
-                                                          renderer, "text",
-                                                          column, NULL);
-           gtk_tree_view_column_set_sizing(tc, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
-            gtk_tree_view_append_column(list, tc);
-        }
-#endif
+    /* Initialize list */
+    store = gtk_list_store_new(E_LIST_D_COLUMNS, G_TYPE_STRING,
+                               G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
+    list = GTK_TREE_VIEW(tree_view_new(GTK_TREE_MODEL(store)));
+    gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(list), TRUE);
+    gtk_tree_view_set_headers_clickable(GTK_TREE_VIEW(list), FALSE);
+    gtk_tree_selection_set_mode(gtk_tree_view_get_selection(list),
+                                GTK_SELECTION_NONE);
+
+    for (column = 0; column < E_LIST_D_COLUMNS; column++) {
+        renderer = gtk_cell_renderer_text_new();
+        tc = gtk_tree_view_column_new_with_attributes(titles[column],
+                                                      renderer, "text",
+                                                      column, NULL);
+        gtk_tree_view_column_set_sizing(tc, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
+        gtk_tree_view_append_column(list, tc);
+    }
 
-       /* Add data */
-#if GTK_MAJOR_VERSION < 2
-       dissector_all_tables_foreach_changed(decode_build_show_list, list);
-       gtk_clist_sort(list);
-#else
-       dissector_all_tables_foreach_changed(decode_build_show_list, store);
-       g_object_unref(G_OBJECT(store));
-#endif
+    /* Add data */
+    dissector_all_tables_foreach_changed(decode_build_show_list, store);
+    g_object_unref(G_OBJECT(store));
+    decode_dcerpc_add_show_list(store);
 
-       /* Put clist into a scrolled window */
-       scrolled_window = gtk_scrolled_window_new(NULL, NULL);
-       gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window),
-                                      GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
-       gtk_container_add(GTK_CONTAINER(scrolled_window),
-                          GTK_WIDGET(list));
-       gtk_box_pack_start(GTK_BOX(main_vb), scrolled_window, TRUE, TRUE, 0);
-       /* Provide a minimum of a couple of rows worth of data */
-       WIDGET_SET_SIZE(scrolled_window, -1, E_DECODE_MIN_HEIGHT);
-    }
+    /* Put list into a scrolled window */
+    scrolled_window = scrolled_window_new(NULL, NULL);
+    /* this will result to set the width of the dialog to the required size */
+    gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window),
+                                   GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
+    gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled_window),
+                                        GTK_SHADOW_IN);
+    gtk_container_add(GTK_CONTAINER(scrolled_window),
+                      GTK_WIDGET(list));
+    gtk_box_pack_start(GTK_BOX(main_vb), scrolled_window, TRUE, TRUE, 0);
 
-    /* Button row: OK and reset buttons */
-    bbox = gtk_hbutton_box_new();
-    gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_END);
-    gtk_button_box_set_spacing(GTK_BUTTON_BOX(bbox), 5);
-    gtk_box_pack_start(GTK_BOX(main_vb), bbox, FALSE, FALSE, 10);
+    /* Button row */
+    bbox = dlg_button_row_new(GTK_STOCK_OK, GTK_STOCK_CLEAR, GTK_STOCK_HELP, NULL);
+    gtk_box_pack_start(GTK_BOX(main_vb), bbox, FALSE, FALSE, 0);
+    gtk_widget_show(bbox);
 
-    button = gtk_button_new_with_label("Reset Changes");
-    SIGNAL_CONNECT(button, "clicked", decode_show_reset_cb, decode_show_w);
-    GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
-    gtk_box_pack_start(GTK_BOX(bbox), button, FALSE, FALSE, 0);
-#if GTK_MAJOR_VERSION < 2
-    gtk_widget_set_sensitive(button, (list->rows != 0));
+    ok_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_OK);
+    g_signal_connect(ok_bt, "clicked", G_CALLBACK(decode_show_ok_cb), decode_show_w);
 
-    ok_bt = gtk_button_new_with_label("OK");
-#else
-    gtk_widget_set_sensitive(button,
-                             gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter));
+    clear_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_CLEAR);
+    g_signal_connect(clear_bt, "clicked", G_CALLBACK(decode_show_clear_cb), decode_show_w);
 
-    ok_bt = gtk_button_new_from_stock(GTK_STOCK_OK);
-#endif
-    SIGNAL_CONNECT(ok_bt, "clicked", decode_show_ok_cb, decode_show_w);
-    GTK_WIDGET_SET_FLAGS(ok_bt, GTK_CAN_DEFAULT);
-    gtk_box_pack_start(GTK_BOX(bbox), ok_bt, FALSE, FALSE, 0);
-    gtk_widget_grab_default(ok_bt);
-    dlg_set_cancel(decode_show_w, ok_bt);
+    help_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_HELP);
+    g_signal_connect(help_bt, "clicked", G_CALLBACK(topic_cb), (gpointer)HELP_DECODE_AS_SHOW_DIALOG);
+
+    /* set ok as default, this button won't change anything */
+    window_set_cancel_button(decode_show_w, ok_bt, NULL);
+
+    g_signal_connect(decode_show_w, "delete_event", G_CALLBACK(decode_show_delete_cb), NULL);
+    g_signal_connect(decode_show_w, "destroy", G_CALLBACK(decode_show_destroy_cb), NULL);
+
+    gtk_widget_set_sensitive(clear_bt,
+                             gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter));
 
     gtk_widget_show_all(decode_show_w);
+    window_present(decode_show_w);
 }
 
 
@@ -538,52 +635,33 @@ decode_show_cb (GtkWidget * w _U_, gpointer data _U_)
  * buffer.
  */
 static void
-decode_change_one_dissector(gchar *table_name, gint selector, GtkWidget *list)
+decode_change_one_dissector(gchar *table_name, guint selector, GtkWidget *list)
 {
     dissector_handle_t handle;
     gchar              *abbrev;
-#if GTK_MAJOR_VERSION < 2
-    gint               row;
-#else
     GtkTreeSelection  *selection;
     GtkTreeModel      *model;
     GtkTreeIter        iter;
-#endif
 
-#if GTK_MAJOR_VERSION < 2
-    if (!GTK_CLIST(list)->selection)
-    {
-       abbrev = "(NULL)";
-       handle = NULL;
-    } else {
-       row = GPOINTER_TO_INT(GTK_CLIST(list)->selection->data);
-       handle = gtk_clist_get_row_data(GTK_CLIST(list), row);
-       gtk_clist_get_text(GTK_CLIST(list), row, E_LIST_S_PROTO_NAME, &abbrev);
-    }
-#else
     selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(list));
     if (gtk_tree_selection_get_selected(selection, &model, &iter) == FALSE)
     {
-       abbrev = "(NULL)";
-       handle = NULL;
+        abbrev = NULL;
+        handle = NULL;
     } else {
         gtk_tree_model_get(model, &iter, E_LIST_S_PROTO_NAME, &abbrev,
                            E_LIST_S_TABLE+1, &handle, -1);
     }
-#endif
 
-    if (strcmp(abbrev, "(default)") == 0) {
-       dissector_reset(table_name, selector);
+    if (abbrev != NULL && strcmp(abbrev, "(default)") == 0) {
+        dissector_reset_uint(table_name, selector);
     } else {
-       dissector_change(table_name, selector, handle);
+        dissector_change_uint(table_name, selector, handle);
     }
-#if GTK_MAJOR_VERSION >= 2
     g_free(abbrev);
-#endif
 }
 
 
-
 /**************************************************/
 /* Action routines for the "Decode As..." dialog  */
 /*   - called when the OK button pressed          */
@@ -593,34 +671,39 @@ decode_change_one_dissector(gchar *table_name, gint selector, GtkWidget *list)
 
 #ifdef DEBUG
 /*
- * Print debugging information about clist selection.  Extract all
- * information from the clist entry that was selected and print it to
+ * Print debugging information about tree view selection.  Extract all
+ * information from the tree view entry that was selected and print it to
  * a dialog window.
  *
- * @param clist The clist to dump.
+ * @param tree_view The tree view to dump.
  *
  * @param leadin A string to print at the start of each line.
  */
 static void
-decode_debug (GtkCList *clist, gchar *leadin)
+decode_debug (GtkTreeView *tree_view, gchar *leadin)
 {
-    gchar *string, *text[E_LIST_S_COLUMNS];
+    GtkListStore *store;
+    GtkTreeSelection *selection;
+    GtkTreeIter iter;
+    char *string, *text[E_LIST_S_COLUMNS];
     dissector_handle_t handle;
-    gint row;
-
-    string = g_malloc(1024);
-    if (clist->selection) {
-       row = GPOINTER_TO_INT(clist->selection->data);
-       gtk_clist_get_text(clist, row, E_LIST_S_PROTO_NAME, &text[E_LIST_S_PROTO_NAME]);
-       gtk_clist_get_text(clist, row, E_LIST_S_TABLE, &text[E_LIST_S_TABLE]);
-       handle = gtk_clist_get_row_data(clist, row);
-       sprintf(string, "%s clist row %d: <put handle here>, name %s, table %s",
-               leadin, row, text[E_LIST_S_PROTO_NAME],
-               text[E_LIST_S_TABLE]);
+
+    selection = gtk_tree_view_get_selection(tree_view);
+
+    if (gtk_tree_selection_get_selected(selection, NULL, &iter)){
+        store = GTK_LIST_STORE(gtk_tree_view_get_model(tree_view));
+        gtk_tree_model_get(GTK_TREE_MODEL(store), &iter,
+                           E_LIST_S_PROTO_NAME, &text[E_LIST_S_PROTO_NAME],
+                           E_LIST_S_TABLE, &text[E_LIST_S_TABLE],
+                           E_LIST_S_TABLE+1, &handle,
+                           -1);
+        string = g_strdup_printf("%s list: <put handle here>, name %s, table %s",
+                                 leadin, text[E_LIST_S_PROTO_NAME],
+                                 text[E_LIST_S_TABLE]);
     } else {
-       sprintf(string, "%s clist row (none), aka do not decode", leadin);
+        string = g_strdup_printf("%s list row (none), aka do not decode", leadin);
     }
-    simple_dialog(ESD_TYPE_INFO, NULL, string);
+    simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK, string);
     g_free(string);
 }
 #endif
@@ -644,23 +727,19 @@ decode_simple (GtkWidget *notebook_pg)
     gchar *string;
 #endif
     gchar *table_name;
-    gint value;
+    guint value;
 
-    list = OBJECT_GET_DATA(notebook_pg, E_PAGE_LIST);
+    list = g_object_get_data(G_OBJECT(notebook_pg), E_PAGE_LIST);
     if (requested_action == E_DECODE_NO)
-#if GTK_MAJOR_VERSION < 2
-       gtk_clist_unselect_all(GTK_CLIST(list));
-#else
-       gtk_tree_selection_unselect_all(gtk_tree_view_get_selection(GTK_TREE_VIEW(list)));
-#endif
+        gtk_tree_selection_unselect_all(gtk_tree_view_get_selection(GTK_TREE_VIEW(list)));
 
 #ifdef DEBUG
-    string = OBJECT_GET_DATA(notebook_pg, E_PAGE_TITLE);
-    decode_debug(GTK_CLIST(list), string);
+    string = g_object_get_data(G_OBJECT(notebook_pg), E_PAGE_TITLE);
+    decode_debug(GTK_TREE_VIEW(list), string);
 #endif
 
-    table_name = OBJECT_GET_DATA(notebook_pg, E_PAGE_TABLE);
-    value = GPOINTER_TO_INT(OBJECT_GET_DATA(notebook_pg, E_PAGE_VALUE));
+    table_name = g_object_get_data(G_OBJECT(notebook_pg), E_PAGE_TABLE);
+    value = GPOINTER_TO_UINT(g_object_get_data(G_OBJECT(notebook_pg), E_PAGE_VALUE));
     decode_change_one_dissector(table_name, value, list);
 }
 
@@ -676,36 +755,59 @@ decode_simple (GtkWidget *notebook_pg)
 static void
 decode_transport(GtkWidget *notebook_pg)
 {
-    GtkWidget *menu, *menuitem;
+    GtkWidget *combo_box;
     GtkWidget *list;
     gchar *table_name;
-    gint requested_srcdst;
-
-    list = OBJECT_GET_DATA(notebook_pg, E_PAGE_LIST);
-    if (requested_action == E_DECODE_NO)
-#if GTK_MAJOR_VERSION < 2
-       gtk_clist_unselect_all(GTK_CLIST(list));
-#else
-       gtk_tree_selection_unselect_all(gtk_tree_view_get_selection(GTK_TREE_VIEW(list)));
+    gint requested_srcdst, requested_port, ppid;
+    gpointer portp;
+    gpointer ptr;
+#ifdef DEBUG
+    gchar *string;
 #endif
 
-    menu = OBJECT_GET_DATA(notebook_pg, E_MENU_SRCDST);
+    list = g_object_get_data(G_OBJECT(notebook_pg), E_PAGE_LIST);
+    if (requested_action == E_DECODE_NO)
+        gtk_tree_selection_unselect_all(gtk_tree_view_get_selection(GTK_TREE_VIEW(list)));
 
-    menuitem = gtk_menu_get_active(GTK_MENU(menu));
-    requested_srcdst = GPOINTER_TO_INT(OBJECT_GET_DATA(menuitem, "user_data"));
+    combo_box = g_object_get_data(G_OBJECT(notebook_pg), E_COMBO_BOX_SRCDST);
+    if (!ws_combo_box_get_active_pointer(GTK_COMBO_BOX(combo_box), &ptr))
+        g_assert_not_reached();  /* Programming error if no active item in combo_box */
+    requested_srcdst = GPOINTER_TO_INT(ptr);
 
 #ifdef DEBUG
-    string = OBJECT_GET_DATA(notebook_pg, E_PAGE_TITLE);
-    decode_debug(GTK_CLIST(list), string);
+    string = g_object_get_data(G_OBJECT(notebook_pg), E_PAGE_TITLE);
+    decode_debug(GTK_TREE_VIEW(list), string);
 #endif
 
-    table_name = OBJECT_GET_DATA(notebook_pg, E_PAGE_TABLE);
-    if (requested_srcdst != E_DECODE_DPORT)
-       decode_change_one_dissector(table_name, cfile.edt->pi.srcport, list);
-    if (requested_srcdst != E_DECODE_SPORT)
-       decode_change_one_dissector(table_name, cfile.edt->pi.destport, list);
+    table_name = g_object_get_data(G_OBJECT(notebook_pg), E_PAGE_TABLE);
+    if (requested_srcdst >= E_DECODE_PPID) {
+        if (requested_srcdst == E_DECODE_PPID)
+            ppid = 0;
+        else
+           if (requested_srcdst - E_DECODE_PPID - 1 < MAX_NUMBER_OF_PPIDS)
+             ppid = cfile.edt->pi.ppids[requested_srcdst - E_DECODE_PPID - 1];
+           else
+             return;
+        decode_change_one_dissector(table_name, ppid, list);
+        return;
+    }
+    if (requested_srcdst != E_DECODE_DPORT) {
+        portp = g_object_get_data(G_OBJECT(notebook_pg), E_PAGE_SPORT);
+        if (portp != NULL) {
+            requested_port = GPOINTER_TO_INT(portp);
+            decode_change_one_dissector(table_name, requested_port, list);
+        }
+    }
+    if (requested_srcdst != E_DECODE_SPORT) {
+        portp = g_object_get_data(G_OBJECT(notebook_pg), E_PAGE_DPORT);
+        if (portp != NULL) {
+            requested_port = GPOINTER_TO_INT(portp);
+            decode_change_one_dissector(table_name, requested_port, list);
+        }
+    }
 }
 
+
 /**************************************************/
 /*      Signals from the "Decode As..." dialog    */
 /**************************************************/
@@ -729,21 +831,29 @@ decode_ok_cb (GtkWidget *ok_bt _U_, gpointer parent_w)
     GtkWidget *notebook, *notebook_pg;
     void (* func)(GtkWidget *);
     gint page_num;
+    void *binding = NULL;
 
     /* Call the right routine for the page that was currently in front. */
-    notebook =  OBJECT_GET_DATA(parent_w, E_NOTEBOOK);
+    notebook =  g_object_get_data(G_OBJECT(parent_w), E_NOTEBOOK);
     page_num = gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook));
     notebook_pg = gtk_notebook_get_nth_page(GTK_NOTEBOOK(notebook), page_num);
 
-    func = OBJECT_GET_DATA(notebook_pg, E_PAGE_ACTION);
+    func = g_object_get_data(G_OBJECT(notebook_pg), E_PAGE_ACTION);
     func(notebook_pg);
 
     /* Now destroy the "Decode As" dialog. */
-    gtk_widget_destroy(GTK_WIDGET(parent_w));
+    notebook_pg = g_object_get_data(G_OBJECT(parent_w), E_PAGE_DCERPC);
+    if(notebook_pg) {
+        binding = g_object_get_data(G_OBJECT(notebook_pg), E_PAGE_BINDING);
+    }
+    if(binding) {
+        decode_dcerpc_binding_free(binding);
+    }
+    window_destroy(GTK_WIDGET(parent_w));
     g_slist_free(decode_dimmable);
     decode_dimmable = NULL;
 
-    redissect_packets(&cfile);
+    redissect_packets();
 }
 
 /*
@@ -765,29 +875,40 @@ decode_apply_cb (GtkWidget *apply_bt _U_, gpointer parent_w)
     gint page_num;
 
     /* Call the right routine for the page that was currently in front. */
-    notebook =  OBJECT_GET_DATA(parent_w, E_NOTEBOOK);
+    notebook =  g_object_get_data(G_OBJECT(parent_w), E_NOTEBOOK);
     page_num = gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook));
     notebook_pg = gtk_notebook_get_nth_page(GTK_NOTEBOOK(notebook), page_num);
 
-    func = OBJECT_GET_DATA(notebook_pg, E_PAGE_ACTION);
+    func = g_object_get_data(G_OBJECT(notebook_pg), E_PAGE_ACTION);
     func(notebook_pg);
 
-    redissect_packets(&cfile);
+    redissect_packets();
 }
 
 /*
- * This routine is called when the user clicks the "Cancel" button in
+ * This routine is called when the user clicks the "Close" button in
  * the "Decode As..." dialog window.  This routine then destroys the
  * dialog box and performs other housekeeping functions.
  *
- * @param cancel_bt A pointer to the "Cancel" button.
+ * @param close_bt A pointer to the "Close" button.
  *
  * @param parent_w A pointer to the dialog window.
  */
 static void
-decode_cancel_cb (GtkWidget *cancel_bt _U_, gpointer parent_w)
+decode_close_cb (GtkWidget *close_bt _U_, gpointer parent_w)
 {
-    gtk_widget_destroy(GTK_WIDGET(parent_w));
+    GtkWidget *notebook_pg = NULL;
+    void *binding = NULL;
+
+
+    notebook_pg = g_object_get_data(G_OBJECT(parent_w), E_PAGE_DCERPC);
+    if(notebook_pg) {
+        binding = g_object_get_data(G_OBJECT(notebook_pg), E_PAGE_BINDING);
+    }
+    if(binding) {
+        decode_dcerpc_binding_free(binding);
+    }
+    window_destroy(GTK_WIDGET(parent_w));
     g_slist_free(decode_dimmable);
     decode_dimmable = NULL;
 }
@@ -796,17 +917,19 @@ decode_cancel_cb (GtkWidget *cancel_bt _U_, gpointer parent_w)
 /*
  * This routine is called when the user clicks the "Close" button in
  * the "Decode As..." dialog window.  This routine simply calls the
- * cancel routine as if the user had clicked the cancel button instead
+ * close routine as if the user had clicked the close button instead
  * of the close button.
  *
- * @param decode_w A pointer to the dialog box.
+ * @param decode_w_lcl A pointer to the dialog box.
+ *
+ * @param event    A pointer to the GdkEvent struct
  *
- * @param dummy Unknown
+ * @param user_data Unused
  */
 static gboolean
-decode_delete_cb (GtkWidget *decode_w, gpointer dummy _U_)
+decode_delete_cb (GtkWidget *decode_w_lcl, GdkEvent *event _U_, gpointer user_data _U_)
 {
-    decode_cancel_cb(NULL, decode_w);
+    decode_close_cb(NULL, decode_w_lcl);
     return FALSE;
 }
 
@@ -817,9 +940,9 @@ decode_delete_cb (GtkWidget *decode_w, gpointer dummy _U_)
  * the next time the user selects the "Decode As..." menu item a new
  * dialog box will be created.
  *
- * @param decode_w A pointer to the dialog box.
+ * @param win A pointer to the dialog box.
  *
- * @param user_data Unknown
+ * @param user_data Unused
  *
  * @return void
  */
@@ -831,6 +954,23 @@ decode_destroy_cb (GtkWidget *win _U_, gpointer user_data _U_)
 }
 
 
+/*
+ * This routine is called when the user clicks the "Clear" button in
+ * the "Decode As..." dialog window.  This routine resets all the
+ * dissector values and performs other housekeeping functions.
+ *
+ * @param clear_bt A pointer to the "Clear" button.
+ *
+ * @param user_data Unused
+ */
+static void
+decode_clear_cb(GtkWidget *clear_bt _U_, gpointer user_data _U_)
+{
+    decode_clear_all();
+}
+
+
+
 /**************************************************/
 /*          Dialog setup - radio buttons          */
 /**************************************************/
@@ -842,19 +982,19 @@ decode_destroy_cb (GtkWidget *win _U_, gpointer user_data _U_)
  *
  * @param w The radio button that was clicked.
  *
- * @param data The enum value assigned to this radio button.  This
+ * @param user_data The enum value assigned to this radio button.  This
  * will be either E_DECODE_YES or E_DECODE_NO
  */
 static void
-decode_update_action (GtkWidget *w _U_, gpointer data)
+decode_update_action (GtkWidget *w _U_, gpointer user_data)
 {
     GSList *tmp;
     gboolean enable;
 
-    requested_action = GPOINTER_TO_INT(data);
+    requested_action = GPOINTER_TO_INT(user_data);
     enable = (requested_action == E_DECODE_YES);
     for (tmp = decode_dimmable; tmp; tmp = g_slist_next(tmp)) {
-       gtk_widget_set_sensitive(tmp->data, enable);
+        gtk_widget_set_sensitive(tmp->data, enable);
     }
 }
 
@@ -868,21 +1008,20 @@ decode_update_action (GtkWidget *w _U_, gpointer data)
 static GtkWidget *
 decode_add_yes_no (void)
 {
-    GtkWidget  *format_vb, *radio_button;
-    GSList     *format_grp;
+    GtkWidget   *format_vb, *radio_button;
+    GSList      *format_grp;
 
     format_vb = gtk_vbox_new(FALSE, 2);
 
     radio_button = gtk_radio_button_new_with_label(NULL, "Decode");
-    format_grp = gtk_radio_button_group(GTK_RADIO_BUTTON(radio_button));
+    format_grp = gtk_radio_button_get_group(GTK_RADIO_BUTTON(radio_button));
     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio_button), TRUE);
-    SIGNAL_CONNECT(radio_button, "clicked", decode_update_action,
+    g_signal_connect(radio_button, "clicked", G_CALLBACK(decode_update_action),
                    GINT_TO_POINTER(E_DECODE_YES));
     gtk_box_pack_start(GTK_BOX(format_vb), radio_button, TRUE, TRUE, 0);
 
     radio_button = gtk_radio_button_new_with_label(format_grp, "Do not decode");
-    format_grp = gtk_radio_button_group(GTK_RADIO_BUTTON(radio_button));
-    SIGNAL_CONNECT(radio_button, "clicked", decode_update_action,
+    g_signal_connect(radio_button, "clicked", G_CALLBACK(decode_update_action),
                    GINT_TO_POINTER(E_DECODE_NO));
     gtk_box_pack_start(GTK_BOX(format_vb), radio_button, TRUE, TRUE, 0);
 
@@ -890,80 +1029,98 @@ decode_add_yes_no (void)
 }
 
 /**************************************************/
-/*          Dialog setup - simple menus           */
+/*          Dialog setup - simple combo_boxes     */
 /**************************************************/
 
 /*
- * This routine is called to pack an option menu into an aligment, so
+ * This routine is called to pack an combo_box into an aligment, so
  * that it doesn't expand vertically to fill up the space available to
  * it.
  *
- * @param optmenu A pointer to the option menu to be so packed.
+ * @param combo_box A pointer to the option menu to be so packed.
  *
  * @return GtkWidget * A pointer to the newly created alignment.
  */
 static GtkWidget *
-decode_add_pack_menu (GtkWidget *optmenu)
+decode_add_pack_combo_box (GtkWidget *combo_box)
 {
     GtkWidget *alignment;
 
-    alignment = gtk_alignment_new(0.0, 0.5, 0.0, 0.0);
-    gtk_container_add(GTK_CONTAINER(alignment), optmenu);
+    alignment = gtk_alignment_new(0.0f, 0.5f, 0.0f, 0.0f);
+    gtk_container_add(GTK_CONTAINER(alignment), combo_box);
 
     return(alignment);
 }
 
 
 /*
- * This routine is called to add the transport port selection menu to
- * the dialog box.  This is a three choice menu: source, destination
- * and both.  The default choice for the menu is set to the source
+ * This routine is called to add the transport port selection combo_box to
+ * the dialog box.  This is a three choice combo_box: source, destination
+ * and both.  The default choice for the combo_box is set to the source
  * port number of the currently selected packet.
  *
  * @param page A pointer notebook page that will contain all
  * widgets created by this routine.
  *
  * @return GtkWidget * A pointer to the newly created alignment into
- * which we've packed the newly created option menu.
+ * which we've packed the newly created combo_box.
  */
 static GtkWidget *
-decode_add_srcdst_menu (GtkWidget *page)
+decode_add_srcdst_combo_box (GtkWidget *page)
 {
-    GtkWidget *optmenu, *menu, *menuitem, *alignment;
+    GtkWidget *combo_box, *alignment;
     gchar      tmp[100];
 
-    optmenu = gtk_option_menu_new();
-    menu = gtk_menu_new();
-    sprintf(tmp, "source (%u)", cfile.edt->pi.srcport);
-    menuitem = gtk_menu_item_new_with_label(tmp);
-    OBJECT_SET_DATA(menuitem, "user_data", GINT_TO_POINTER(E_DECODE_SPORT));
-    gtk_menu_append(GTK_MENU(menu), menuitem);
-    gtk_widget_show(menuitem); /* gtk_widget_show_all() doesn't show this */
+    combo_box = ws_combo_box_new_text_and_pointer();
 
-    sprintf(tmp, "destination (%u)", cfile.edt->pi.destport);
-    menuitem = gtk_menu_item_new_with_label(tmp);
-    OBJECT_SET_DATA(menuitem, "user_data", GINT_TO_POINTER(E_DECODE_DPORT));
-    gtk_menu_append(GTK_MENU(menu), menuitem);
-    gtk_widget_show(menuitem); /* gtk_widget_show_all() doesn't show this */
+    g_snprintf(tmp, sizeof(tmp), "Source (%u%s)", cfile.edt->pi.srcport, UTF8_RIGHTWARDS_ARROW);
+    ws_combo_box_append_text_and_pointer(GTK_COMBO_BOX(combo_box), tmp, GINT_TO_POINTER(E_DECODE_SPORT));
 
-    menuitem = gtk_menu_item_new_with_label("both");
-    OBJECT_SET_DATA(menuitem, "user_data", GINT_TO_POINTER(E_DECODE_BPORT));
-    gtk_menu_append(GTK_MENU(menu), menuitem);
-    gtk_widget_show(menuitem); /* gtk_widget_show_all() doesn't show this */
+    g_snprintf(tmp, sizeof(tmp), "Destination (%s%u)", UTF8_RIGHTWARDS_ARROW, cfile.edt->pi.destport);
+    ws_combo_box_append_text_and_pointer(GTK_COMBO_BOX(combo_box), tmp, GINT_TO_POINTER(E_DECODE_DPORT));
 
-    OBJECT_SET_DATA(page, E_MENU_SRCDST, menu);
-    gtk_option_menu_set_menu(GTK_OPTION_MENU(optmenu), menu);
+    g_snprintf(tmp, sizeof(tmp), "Both (%u%s%u)", cfile.edt->pi.srcport,UTF8_LEFT_RIGHT_ARROW, cfile.edt->pi.destport);
+    ws_combo_box_append_text_and_pointer(GTK_COMBO_BOX(combo_box), tmp, GINT_TO_POINTER(E_DECODE_BPORT));
+    ws_combo_box_set_active(GTK_COMBO_BOX(combo_box), 2); /* default "both" */
+    g_object_set_data(G_OBJECT(page), E_COMBO_BOX_SRCDST, combo_box);
 
-    alignment = decode_add_pack_menu(optmenu);
+    g_object_set_data(G_OBJECT(page), E_PAGE_SPORT, GINT_TO_POINTER(cfile.edt->pi.srcport));
+    g_object_set_data(G_OBJECT(page), E_PAGE_DPORT, GINT_TO_POINTER(cfile.edt->pi.destport));
 
+    alignment = decode_add_pack_combo_box(combo_box);
     return(alignment);
 }
 
+static GtkWidget *
+decode_add_ppid_combo_box (GtkWidget *page)
+{
+    GtkWidget *combo_box;
+    gchar      tmp[100];
+    guint      number_of_ppid;
+
+    combo_box = ws_combo_box_new_text_and_pointer();
+
+    g_snprintf(tmp, sizeof(tmp), "PPID (%u)", 0);
+    ws_combo_box_append_text_and_pointer(GTK_COMBO_BOX(combo_box),
+                                         tmp, GINT_TO_POINTER(E_DECODE_PPID));
+    ws_combo_box_set_active(GTK_COMBO_BOX(combo_box), 0);  /* default */
+
+    for(number_of_ppid = 0; number_of_ppid < MAX_NUMBER_OF_PPIDS; number_of_ppid++) {
+      if (cfile.edt->pi.ppids[number_of_ppid] != 0) {
+          g_snprintf(tmp, sizeof(tmp), "PPID (%u)", cfile.edt->pi.ppids[number_of_ppid]);
+          ws_combo_box_append_text_and_pointer(GTK_COMBO_BOX(combo_box),
+                                               tmp, GINT_TO_POINTER(E_DECODE_PPID + 1 + number_of_ppid));
+      } else
+          break;
+    }
+    g_object_set_data(G_OBJECT(page), E_COMBO_BOX_SRCDST, combo_box);
+    return(combo_box);
+}
+
 /*************************************************/
 /*        Dialog setup - list based menus        */
 /*************************************************/
 
-#if GTK_MAJOR_VERSION >= 2
 struct handle_lookup_info {
     dissector_handle_t handle;
     gboolean           found;
@@ -971,10 +1128,10 @@ struct handle_lookup_info {
 
 static gboolean
 lookup_handle(GtkTreeModel *model, GtkTreePath *path _U_, GtkTreeIter *iter,
-              gpointer data)
+              gpointer user_data)
 {
     dissector_handle_t handle;
-    struct handle_lookup_info *hli = (struct handle_lookup_info *)data;
+    struct handle_lookup_info *hli = user_data;
 
     gtk_tree_model_get(model, iter, E_LIST_S_TABLE+1, &handle, -1);
     if (hli->handle == handle) {
@@ -983,7 +1140,6 @@ lookup_handle(GtkTreeModel *model, GtkTreePath *path _U_, GtkTreeIter *iter,
     }
     return FALSE;
 }
-#endif
 
 /*
  * This routine creates one entry in the list of protocol dissector
@@ -997,6 +1153,8 @@ lookup_handle(GtkTreeModel *model, GtkTreePath *path _U_, GtkTreeIter *iter,
  * @param table_name The name of the dissector table currently
  * being walked.
  *
+ * @param proto_name The protocol name
+ *
  * @param value The dissector handle for this entry.  This is an opaque
  * pointer that can only be handed back to routines in the file packet.c
  *
@@ -1005,58 +1163,79 @@ lookup_handle(GtkTreeModel *model, GtkTreePath *path _U_, GtkTreeIter *iter,
  * routine, specifying information about the dissector table and where
  * to store any information generated by this routine.
  */
-static void
-decode_add_to_list (gchar *table_name, gpointer value, gpointer user_data)
+void
+decode_add_to_list (const gchar *table_name, const gchar *proto_name, gpointer value, gpointer user_data)
 {
-    gchar     *proto_name;
-    gchar     *text[E_LIST_S_COLUMNS];
-    dissector_handle_t handle;
-#if GTK_MAJOR_VERSION < 2
-    GtkCList  *list;
-    gint       row;
-#else
+    const gchar     *text[E_LIST_S_COLUMNS];
     GtkTreeView  *list;
     GtkListStore *store;
     GtkTreeIter   iter;
     struct handle_lookup_info hli;
-#endif
 
     g_assert(user_data);
     g_assert(value);
 
     list = user_data;
-    handle = value;
-    proto_name = dissector_handle_get_short_name(handle);
 
-#if GTK_MAJOR_VERSION < 2
-    row = gtk_clist_find_row_from_data(list, handle);
-    /* We already have an entry for this handle.
-     * XXX - will this ever happen? */
-    if (row != -1) return;
-#else
-    hli.handle = handle;
+    hli.handle = value;
     hli.found = FALSE;
     store = GTK_LIST_STORE(gtk_tree_view_get_model(list));
     gtk_tree_model_foreach(GTK_TREE_MODEL(store), lookup_handle, &hli);
     /* We already have an entry for this handle.
      * XXX - will this ever happen? */
     if (hli.found) return;
-#endif
 
     text[E_LIST_S_PROTO_NAME] = proto_name;
     text[E_LIST_S_TABLE] = table_name;
-#if GTK_MAJOR_VERSION < 2
-    row = gtk_clist_prepend(list, text);
-    gtk_clist_set_row_data(list, row, handle);
-#else
     gtk_list_store_append(store, &iter);
     gtk_list_store_set(store, &iter,
                        E_LIST_S_PROTO_NAME, text[E_LIST_S_PROTO_NAME],
                        E_LIST_S_TABLE, text[E_LIST_S_TABLE],
-                       E_LIST_S_TABLE+1, handle, -1);
-#endif
+                       E_LIST_S_TABLE+1, value, -1);
 }
 
+static void
+decode_proto_add_to_list (const gchar *table_name, gpointer value, gpointer user_data)
+{
+    const gchar     *proto_name;
+    gint       i;
+    dissector_handle_t handle;
+
+
+    handle = value;
+    proto_name = dissector_handle_get_short_name(handle);
+
+    i = dissector_handle_get_protocol_index(handle);
+    if (i >= 0 && !proto_is_protocol_enabled(find_protocol_by_id(i)))
+        return;
+
+    decode_add_to_list (table_name, proto_name, value, user_data);
+}
+
+
+static gboolean
+decode_list_button_press_cb(GtkWidget *list, GdkEventButton *event, gpointer user_data _U_)
+{
+  if (event->type == GDK_2BUTTON_PRESS) {
+    GtkWidget *main_w = gtk_widget_get_toplevel(list);
+
+    decode_ok_cb (NULL, main_w);
+  }
+
+  return FALSE;
+}
+
+static gboolean
+decode_list_key_release_cb(GtkWidget *list, GdkEventKey *event, gpointer user_data _U_)
+{
+  if (event->keyval == GDK_Return || event->keyval == GDK_KP_Enter) {
+    GtkWidget    *main_w = gtk_widget_get_toplevel(list);
+
+    decode_ok_cb (NULL, main_w);
+  }
+
+  return FALSE;
+}
 
 /*
  * This routine starts the creation of a List on a notebook page.  It
@@ -1071,37 +1250,24 @@ decode_add_to_list (gchar *table_name, gpointer value, gpointer user_data)
  * @param scrolled_win_p Will be filled in with the address of a newly
  * created GtkScrolledWindow.
  */
-static void
+void
 decode_list_menu_start(GtkWidget *page, GtkWidget **list_p,
                        GtkWidget **scrolled_win_p)
 {
-    GtkWidget *window;
-#if GTK_MAJOR_VERSION < 2
-    gchar             *titles[E_LIST_S_COLUMNS] = {"Short Name", "Table Name"};
-    GtkCList          *list;
-    gint               column;
-#else
     GtkTreeView       *list;
     GtkListStore      *store;
     GtkCellRenderer   *renderer;
     GtkTreeViewColumn *tc;
-#endif
+    GtkTreeSortable   *sortable;
 
-#if GTK_MAJOR_VERSION < 2
-    list = GTK_CLIST(gtk_clist_new_with_titles(E_LIST_S_COLUMNS, titles));
-    gtk_clist_column_titles_passive(list);
-#ifndef DEBUG
-    gtk_clist_column_titles_hide(list);
-    for (column = 1; column < E_LIST_S_COLUMNS; column++)
-       gtk_clist_set_column_visibility (list, column, FALSE);
-#endif
-    for (column = 0; column < E_LIST_S_COLUMNS; column++)
-       gtk_clist_set_column_auto_resize(list, column, TRUE);
-    OBJECT_SET_DATA(page, E_PAGE_LIST, list);
-#else
     store = gtk_list_store_new(E_LIST_S_COLUMNS+1, G_TYPE_STRING,
                                G_TYPE_STRING, G_TYPE_POINTER);
+    g_object_set_data(G_OBJECT(decode_w), "sctp_data", store);
     list = GTK_TREE_VIEW(tree_view_new(GTK_TREE_MODEL(store)));
+    g_object_unref(G_OBJECT(store));
+    sortable = GTK_TREE_SORTABLE(store);
+    gtk_tree_sortable_set_sort_func(sortable, SORT_ALPHABETICAL, sort_iter_compare_func, GINT_TO_POINTER(SORT_ALPHABETICAL), NULL);
+    gtk_tree_sortable_set_sort_column_id(sortable, SORT_ALPHABETICAL, GTK_SORT_ASCENDING);
     gtk_tree_view_set_headers_clickable(list, FALSE);
 #ifndef DEBUG
     gtk_tree_view_set_headers_visible(list, FALSE);
@@ -1113,19 +1279,14 @@ decode_list_menu_start(GtkWidget *page, GtkWidget **list_p,
     gtk_tree_view_column_set_sizing(tc, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
     gtk_tree_view_append_column(list, tc);
     g_object_set_data(G_OBJECT(page), E_PAGE_LIST, list);
-#endif
 
-    *scrolled_win_p = window = gtk_scrolled_window_new(NULL, NULL);
-    /* Provide a minimum of a couple of rows worth of data */
-    WIDGET_SET_SIZE(window, -1, E_DECODE_MIN_HEIGHT);
-    gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(window),
-                                  GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
-#if GTK_MAJOR_VERSION < 2
-    gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(window),
-                                         GTK_WIDGET(list));
-#else
-    gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(list));
-#endif
+    *scrolled_win_p = scrolled_window_new(NULL, NULL);
+    /* this will result to set the width of the dialog to the required size */
+    gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(*scrolled_win_p),
+                                   GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
+    gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(*scrolled_win_p),
+                                   GTK_SHADOW_IN);
+    gtk_container_add(GTK_CONTAINER(*scrolled_win_p), GTK_WIDGET(list));
 
     *list_p = GTK_WIDGET(list);
 }
@@ -1137,26 +1298,15 @@ decode_list_menu_start(GtkWidget *page, GtkWidget **list_p,
  *
  * @param list A pointer the the List to finish.
  */
-static void
+void
 decode_list_menu_finish(GtkWidget *list)
 {
-    gchar *text[E_LIST_S_COLUMNS];
-#if GTK_MAJOR_VERSION < 2
-    gint row;
-#else
+    const gchar *text[E_LIST_S_COLUMNS];
     GtkListStore *store;
     GtkTreeIter   iter;
-#endif
 
     text[E_LIST_S_PROTO_NAME] = "(default)";
     text[E_LIST_S_TABLE] = "(none)";
-#if GTK_MAJOR_VERSION < 2
-    row = gtk_clist_prepend(GTK_CLIST(list), text);
-    gtk_clist_set_row_data(GTK_CLIST(list), row, NULL);
-
-    gtk_clist_select_row(GTK_CLIST(list), 0, -1);
-    gtk_clist_sort(GTK_CLIST(list));
-#else
     store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(list)));
     gtk_list_store_prepend(store, &iter);
     gtk_list_store_set(store, &iter,
@@ -1165,7 +1315,8 @@ decode_list_menu_finish(GtkWidget *list)
                        E_LIST_S_TABLE+1, NULL, -1);
 
     gtk_tree_selection_select_iter(gtk_tree_view_get_selection(GTK_TREE_VIEW(list)), &iter);
-#endif
+    g_signal_connect(list, "button_press_event", G_CALLBACK(decode_list_button_press_cb), NULL);
+    g_signal_connect(list, "key_release_event", G_CALLBACK(decode_list_key_release_cb), NULL);
 }
 
 /*
@@ -1185,17 +1336,18 @@ decode_list_menu_finish(GtkWidget *list)
  * scrolled window.
  */
 static GtkWidget *
-decode_add_simple_menu (GtkWidget *page, gchar *table_name)
+decode_add_simple_menu (GtkWidget *page, const gchar *table_name)
 {
     GtkWidget *scrolled_window;
     GtkWidget *list;
 
     decode_list_menu_start(page, &list, &scrolled_window);
-    dissector_table_foreach_handle(table_name, decode_add_to_list, list);
+    dissector_table_foreach_handle(table_name, decode_proto_add_to_list, list);
     decode_list_menu_finish(list);
     return(scrolled_window);
 }
 
+
 /**************************************************/
 /*                  Dialog setup                  */
 /**************************************************/
@@ -1221,16 +1373,16 @@ decode_add_simple_menu (GtkWidget *page, gchar *table_name)
  * routine.
  */
 static GtkWidget *
-decode_add_simple_page (gchar *prompt, gchar *title, gchar *table_name,
-                       gint value)
+decode_add_simple_page (const gchar *prompt, const gchar *title, const gchar *table_name,
+                        guint value)
 {
-    GtkWidget  *page, *label, *scrolled_window;
+    GtkWidget  *page, *label, *scrolled_window;
 
     page = gtk_hbox_new(FALSE, 5);
-    OBJECT_SET_DATA(page, E_PAGE_ACTION, decode_simple);
-    OBJECT_SET_DATA(page, E_PAGE_TABLE, table_name);
-    OBJECT_SET_DATA(page, E_PAGE_TITLE, title);
-    OBJECT_SET_DATA(page, E_PAGE_VALUE, GINT_TO_POINTER(value));
+    g_object_set_data(G_OBJECT(page), E_PAGE_ACTION, decode_simple);
+    g_object_set_data(G_OBJECT(page), E_PAGE_TABLE, (gchar *) table_name);
+    g_object_set_data(G_OBJECT(page), E_PAGE_TITLE, (gchar *) title);
+    g_object_set_data(G_OBJECT(page), E_PAGE_VALUE, GUINT_TO_POINTER(value));
 
     /* Always enabled */
     label = gtk_label_new(prompt);
@@ -1253,7 +1405,7 @@ decode_add_simple_page (gchar *prompt, gchar *title, gchar *table_name,
  * All items created by this routine are packed into a single
  * horizontal box.  First is a label indicating whether the port(s) for
  * which the user can set the dissection is a TCP port or a UDP port.
- * Second is a menu allowing the user to select whether the source port,
+ * Second is a combo_box allowing the user to select whether the source port,
  * destination port, or both ports will have dissectors added for them.
  * Last is a (conditionally enabled) popup menu listing all possible
  * dissectors that can be used to decode the packets, and the choice
@@ -1272,20 +1424,20 @@ decode_add_simple_page (gchar *prompt, gchar *title, gchar *table_name,
  * this routine.
  */
 static GtkWidget *
-decode_add_tcpudp_page (gchar *prompt, gchar *table_name)
+decode_add_tcpudp_page (const gchar *prompt, const gchar *table_name)
 {
-    GtkWidget  *page, *label, *scrolled_window, *optmenu;
+    GtkWidget  *page, *label, *scrolled_window, *combo_box;
 
     page = gtk_hbox_new(FALSE, 5);
-    OBJECT_SET_DATA(page, E_PAGE_ACTION, decode_transport);
-    OBJECT_SET_DATA(page, E_PAGE_TABLE, table_name);
-    OBJECT_SET_DATA(page, E_PAGE_TITLE, "Transport");
+    g_object_set_data(G_OBJECT(page), E_PAGE_ACTION, decode_transport);
+    g_object_set_data(G_OBJECT(page), E_PAGE_TABLE, (gchar *) table_name);
+    g_object_set_data(G_OBJECT(page), E_PAGE_TITLE, "Transport");
 
     /* Always enabled */
     label = gtk_label_new(prompt);
     gtk_box_pack_start(GTK_BOX(page), label, TRUE, TRUE, 0);
-    optmenu = decode_add_srcdst_menu(page);
-    gtk_box_pack_start(GTK_BOX(page), optmenu, TRUE, TRUE, 0);
+    combo_box = decode_add_srcdst_combo_box(page);
+    gtk_box_pack_start(GTK_BOX(page), combo_box, TRUE, TRUE, 0);
     label = gtk_label_new("port(s)");
     gtk_box_pack_start(GTK_BOX(page), label, TRUE, TRUE, 0);
 
@@ -1300,6 +1452,166 @@ decode_add_tcpudp_page (gchar *prompt, gchar *table_name)
     return(page);
 }
 
+static void
+decode_sctp_list_menu_start(GtkWidget **list_p, GtkWidget **scrolled_win_p)
+{
+    GtkTreeView       *list;
+    GtkListStore      *sctp_store;
+    GtkCellRenderer   *renderer;
+    GtkTreeViewColumn *tc;
+    GtkTreeSortable   *sortable;
+
+    sctp_store = g_object_get_data(G_OBJECT(decode_w), "sctp_data");
+    list = GTK_TREE_VIEW(tree_view_new(GTK_TREE_MODEL(sctp_store)));
+    g_object_unref(G_OBJECT(sctp_store));
+    sortable = GTK_TREE_SORTABLE(sctp_store);
+    gtk_tree_sortable_set_sort_func(sortable, SORT_ALPHABETICAL, sort_iter_compare_func, GINT_TO_POINTER(SORT_ALPHABETICAL), NULL);
+    gtk_tree_sortable_set_sort_column_id(sortable, SORT_ALPHABETICAL, GTK_SORT_ASCENDING);
+    gtk_tree_view_set_headers_clickable(list, FALSE);
+#ifndef DEBUG
+    gtk_tree_view_set_headers_visible(list, FALSE);
+#endif
+    renderer = gtk_cell_renderer_text_new();
+    tc = gtk_tree_view_column_new_with_attributes("Short Name", renderer,
+                                                  "text", E_LIST_S_PROTO_NAME,
+                                                  NULL);
+    gtk_tree_view_column_set_sizing(tc, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
+    gtk_tree_view_append_column(list, tc);
+
+    *scrolled_win_p = scrolled_window_new(NULL, NULL);
+    /* this will result to set the width of the dialog to the required size */
+    gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(*scrolled_win_p), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
+    gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(*scrolled_win_p), GTK_SHADOW_IN);
+    gtk_container_add(GTK_CONTAINER(*scrolled_win_p), GTK_WIDGET(list));
+    *list_p = GTK_WIDGET(list);
+}
+
+static void
+decode_sctp_update_ppid_combo_box(GtkWidget *w _U_, GtkWidget *page)
+{
+    GtkWidget *list, *scrolled_window;
+    GtkWidget *sctp_combo_box;
+    gchar      tmp[100];
+    guint      number_of_ppid;
+    GtkListStore *sctp_store;
+
+    sctp_combo_box = g_object_get_data(G_OBJECT(page), E_COMBO_BOX_SRCDST);
+    ws_combo_box_clear_text_and_pointer(GTK_COMBO_BOX(sctp_combo_box));
+
+    g_snprintf(tmp, sizeof(tmp), "PPID (%u)", 0);
+    ws_combo_box_append_text_and_pointer(GTK_COMBO_BOX(sctp_combo_box), tmp, GINT_TO_POINTER(E_DECODE_PPID));
+    ws_combo_box_set_active(GTK_COMBO_BOX(sctp_combo_box), 0); /* default */
+
+    for(number_of_ppid = 0; number_of_ppid < MAX_NUMBER_OF_PPIDS; number_of_ppid++) {
+      if (cfile.edt->pi.ppids[number_of_ppid] != 0) {
+        g_snprintf(tmp, sizeof(tmp), "PPID (%u)", cfile.edt->pi.ppids[number_of_ppid]);
+        ws_combo_box_append_text_and_pointer(GTK_COMBO_BOX(sctp_combo_box),
+                                             tmp, GINT_TO_POINTER(E_DECODE_PPID + 1 + number_of_ppid));
+      }
+    }
+
+    g_object_set_data(G_OBJECT(page), E_PAGE_TABLE, "sctp.ppi");
+
+    sctp_store = g_object_get_data(G_OBJECT(G_OBJECT(decode_w)), "sctp_data");
+    gtk_list_store_clear(sctp_store);
+    decode_sctp_list_menu_start(&list, &scrolled_window);
+    dissector_table_foreach_handle("sctp.ppi", decode_proto_add_to_list, list);
+    decode_list_menu_finish(list);
+}
+
+
+static void
+decode_sctp_update_srcdst_combo_box(GtkWidget *w _U_, GtkWidget *page)
+{
+    GtkWidget *scrolled_window, *list;
+    GtkWidget *sctp_combo_box;
+    gchar      tmp[100];
+    GtkListStore *sctp_store;
+
+    sctp_combo_box = g_object_get_data(G_OBJECT(page), E_COMBO_BOX_SRCDST);
+    ws_combo_box_clear_text_and_pointer(GTK_COMBO_BOX(sctp_combo_box));
+
+    g_snprintf(tmp, sizeof(tmp), "source (%u)", cfile.edt->pi.srcport);
+    ws_combo_box_append_text_and_pointer(GTK_COMBO_BOX(sctp_combo_box), tmp, GINT_TO_POINTER(E_DECODE_SPORT));
+    g_snprintf(tmp, sizeof(tmp), "destination (%u)", cfile.edt->pi.destport);
+    ws_combo_box_append_text_and_pointer(GTK_COMBO_BOX(sctp_combo_box), tmp, GINT_TO_POINTER(E_DECODE_DPORT));
+    ws_combo_box_append_text_and_pointer(GTK_COMBO_BOX(sctp_combo_box), "both", GINT_TO_POINTER(E_DECODE_BPORT));
+    ws_combo_box_set_active(GTK_COMBO_BOX(sctp_combo_box), 0);
+
+    g_object_set_data(G_OBJECT(page), E_PAGE_TABLE, "sctp.port");
+    g_object_set_data(G_OBJECT(page), E_PAGE_SPORT, GINT_TO_POINTER(cfile.edt->pi.srcport));
+    g_object_set_data(G_OBJECT(page), E_PAGE_DPORT, GINT_TO_POINTER(cfile.edt->pi.destport));
+    sctp_store = g_object_get_data(G_OBJECT(G_OBJECT(decode_w)), "sctp_data");
+    gtk_list_store_clear(sctp_store);
+    decode_sctp_list_menu_start(&list, &scrolled_window);
+    dissector_table_foreach_handle("sctp.port", decode_proto_add_to_list, list);
+    decode_list_menu_finish(list);
+}
+
+
+
+static GtkWidget *
+decode_sctp_add_port_ppid (GtkWidget *page)
+{
+    GtkWidget *format_vb, *radio_button;
+    GSList *format_grp;
+
+    format_vb = gtk_vbox_new(FALSE, 2);
+
+    radio_button = gtk_radio_button_new_with_label(NULL, "PPID");
+    format_grp = gtk_radio_button_get_group(GTK_RADIO_BUTTON(radio_button));
+    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio_button), TRUE);
+    g_signal_connect(radio_button, "clicked", G_CALLBACK(decode_sctp_update_ppid_combo_box), page);
+
+    gtk_box_pack_start(GTK_BOX(format_vb), radio_button, TRUE, TRUE, 0);
+
+    radio_button = gtk_radio_button_new_with_label(format_grp, "Port");
+    g_signal_connect(radio_button, "clicked", G_CALLBACK(decode_sctp_update_srcdst_combo_box), page);
+
+    gtk_box_pack_start(GTK_BOX(format_vb), radio_button, TRUE, TRUE, 0);
+
+    return(format_vb);
+}
+
+
+static GtkWidget *
+decode_add_sctp_page (const gchar *prompt, const gchar *table_name)
+{
+    GtkWidget  *page, *label, *scrolled_window,  *radio, *vbox, *alignment, *sctpbox, *sctp_combo_box;
+
+    page = gtk_hbox_new(FALSE, 5);
+    g_object_set_data(G_OBJECT(page), E_PAGE_ACTION, decode_transport);
+    g_object_set_data(G_OBJECT(page), E_PAGE_TABLE, (gchar *) table_name);
+    g_object_set_data(G_OBJECT(page), E_PAGE_TITLE, "Transport");
+
+    vbox = gtk_vbox_new(FALSE, 5);
+    radio = decode_sctp_add_port_ppid(page);
+    gtk_box_pack_start(GTK_BOX(vbox), radio, TRUE, TRUE, 0);
+
+    /* Always enabled */
+    sctpbox = gtk_hbox_new(FALSE, 5);
+    label = gtk_label_new(prompt);
+    gtk_box_pack_start(GTK_BOX(sctpbox), label, TRUE, TRUE, 0);
+    sctp_combo_box = decode_add_ppid_combo_box(page);
+    alignment = decode_add_pack_combo_box(sctp_combo_box);
+
+    gtk_box_pack_start(GTK_BOX(sctpbox), alignment, TRUE, TRUE, 0);
+
+    /* Conditionally enabled - only when decoding packets */
+    label = gtk_label_new("as");
+    gtk_box_pack_start(GTK_BOX(sctpbox), label, TRUE, TRUE, 0);
+    decode_dimmable = g_slist_prepend(decode_dimmable, label);
+    gtk_box_pack_start(GTK_BOX(vbox), sctpbox, TRUE, TRUE, 0);
+    gtk_box_pack_start(GTK_BOX(page), vbox, TRUE, TRUE, 0);
+
+    scrolled_window = decode_add_simple_menu(page, table_name);
+    gtk_box_pack_start(GTK_BOX(page), scrolled_window, TRUE, TRUE, 0);
+    decode_dimmable = g_slist_prepend(decode_dimmable, scrolled_window);
+
+    return(page);
+}
+
+
 /*
  * This routine indicates whether we'd actually have any pages in the
  * notebook in a "Decode As" dialog box; if there wouldn't be, we
@@ -1308,17 +1620,19 @@ decode_add_tcpudp_page (gchar *prompt, gchar *table_name)
 gboolean
 decode_as_ok(void)
 {
-    return cfile.edt->pi.ethertype || cfile.edt->pi.ipproto ||
-       cfile.edt->pi.ptype == PT_TCP || cfile.edt->pi.ptype == PT_UDP;
+    return (cfile.edt->pi.ethertype != G_MAXINT) || cfile.edt->pi.ipproto ||
+        cfile.edt->pi.ptype == PT_TCP || cfile.edt->pi.ptype == PT_UDP ||
+        cfile.edt->pi.mpls_label ||
+        cfile.cd_t == WTAP_FILE_BER;
 }
 
 
 /*
  * This routine creates the bulk of the "Decode As" dialog box.  All
  * items created by this routine are packed as pages into a notebook.
- * There will be a page for each protocol layer that can be change.
+ * There will be a page for each protocol layer that can be changed.
  *
- * @param GtkWidget * A pointer to the widget in which the notebook
+ * @param format_hb A pointer to the widget in which the notebook
  * should be installed.
  */
 static void
@@ -1330,52 +1644,79 @@ decode_add_notebook (GtkWidget *format_hb)
     /* Start a nootbook for flipping between sets of changes */
     notebook = gtk_notebook_new();
     gtk_container_add(GTK_CONTAINER(format_hb), notebook);
-    OBJECT_SET_DATA(decode_w, E_NOTEBOOK, notebook);
+    g_object_set_data(G_OBJECT(decode_w), E_NOTEBOOK, notebook);
 
     /* Add link level selection page */
-    if (cfile.edt->pi.ethertype) {
-       sprintf(buffer, "Ethertype 0x%04x", cfile.edt->pi.ethertype);
-       page = decode_add_simple_page(buffer, "Link", "ethertype", cfile.edt->pi.ethertype);
-       label = gtk_label_new("Link");
-       gtk_notebook_append_page(GTK_NOTEBOOK(notebook), page, label);
+    if (cfile.edt->pi.ethertype != G_MAXINT) {
+        g_snprintf(buffer, sizeof(buffer), "Ethertype 0x%04x", cfile.edt->pi.ethertype);
+        page = decode_add_simple_page(buffer, "Link", "ethertype", cfile.edt->pi.ethertype);
+        label = gtk_label_new("Link");
+        gtk_notebook_append_page(GTK_NOTEBOOK(notebook), page, label);
+    }
+
+    /* Add mpls selection page */
+    if (cfile.edt->pi.mpls_label) {
+        g_snprintf(buffer, sizeof(buffer), "Data after label %u", cfile.edt->pi.mpls_label);
+        page = decode_add_simple_page(buffer, "MPLS", "mpls.label", cfile.edt->pi.mpls_label);
+        label = gtk_label_new("MPLS");
+        gtk_notebook_append_page(GTK_NOTEBOOK(notebook), page, label);
     }
 
     /* Add network selection page */
     if (cfile.edt->pi.ipproto) {
-       /*
-        * The network-layer protocol is IP.
-        */
-       sprintf(buffer, "IP protocol %u", cfile.edt->pi.ipproto);
-       page = decode_add_simple_page(buffer, "Network", "ip.proto", cfile.edt->pi.ipproto);
-       OBJECT_SET_DATA(page, E_PAGE_ACTION, decode_simple);
-       label = gtk_label_new("Network");
-       gtk_notebook_append_page(GTK_NOTEBOOK(notebook), page, label);
+        /*
+         * The network-layer protocol is IP.
+         */
+        g_snprintf(buffer, sizeof(buffer), "IP protocol %u", cfile.edt->pi.ipproto);
+        page = decode_add_simple_page(buffer, "Network", "ip.proto", cfile.edt->pi.ipproto);
+        g_object_set_data(G_OBJECT(page), E_PAGE_ACTION, decode_simple);
+        label = gtk_label_new("Network");
+        gtk_notebook_append_page(GTK_NOTEBOOK(notebook), page, label);
     }
 
     /* Add transport selection page */
     switch (cfile.edt->pi.ptype) {
 
     case PT_TCP:
-       page = decode_add_tcpudp_page("TCP", "tcp.port");
-       break;
+        page = decode_add_tcpudp_page("TCP", "tcp.port");
+        break;
 
     case PT_UDP:
-       page = decode_add_tcpudp_page("UDP", "udp.port");
-       break;
+        page = decode_add_tcpudp_page("UDP", "udp.port");
+        break;
+
+    case PT_SCTP:
+        page = decode_add_sctp_page("SCTP", "sctp.ppi");
+        break;
 
     default:
-       page = NULL;
-       break;
+        page = NULL;
+        break;
     }
     if (page != NULL) {
-       label = gtk_label_new("Transport");
-       gtk_notebook_append_page(GTK_NOTEBOOK(notebook), page, label);
+        label = gtk_label_new("Transport");
+        gtk_notebook_append_page(GTK_NOTEBOOK(notebook), page, label);
+    }
+
+    if(cfile.edt->pi.dcetransporttype != -1) {
+        page = decode_dcerpc_add_page(&cfile.edt->pi);
+        label = gtk_label_new("DCE-RPC");
+        gtk_notebook_append_page(GTK_NOTEBOOK(notebook), page, label);
+        g_object_set_data(G_OBJECT(decode_w), E_PAGE_DCERPC, page);
+    }
+
+    if(cfile.cd_t == WTAP_FILE_BER) {
+        page = decode_ber_add_page(&cfile.edt->pi);
+        label = gtk_label_new("ASN.1");
+        gtk_notebook_append_page(GTK_NOTEBOOK(notebook), page, label);
+        g_object_set_data(G_OBJECT(decode_w), E_PAGE_ASN1, page);
     }
 
     /* Select the last added page (selects first by default) */
     /* Notebook must be visible for set_page to work. */
     gtk_widget_show_all(notebook);
-    gtk_notebook_set_page(GTK_NOTEBOOK(notebook), -1);
+    gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook), -1);
+
 }
 
 
@@ -1390,95 +1731,87 @@ decode_add_notebook (GtkWidget *format_hb)
  * dialog box, and then hand crafts the button box at the bottom of
  * the dialog.
  *
- * @param w Unknown
- * @param data Unknown
+ * @param w Unused
+ *
+ * @param user_data Unused
  */
 void
-decode_as_cb (GtkWidget * w _U_, gpointer data _U_)
+decode_as_cb (GtkWidget * w _U_, gpointer user_data _U_)
 {
-    GtkWidget  *main_vb, *format_hb, *bbox, *ok_bt, *cancel_bt, *button;
+    GtkWidget   *main_vb, *format_hb, *bbox, *ok_bt, *close_bt, *help_bt, *button;
     GtkWidget   *button_vb, *apply_bt;
 
     if (decode_w != NULL) {
-       /* There's already a "Decode As" dialog box; reactivate it. */
-       reactivate_window(decode_w);
-       return;
+        /* There's already a "Decode As" dialog box; reactivate it. */
+        reactivate_window(decode_w);
+        return;
     }
 
     requested_action = E_DECODE_YES;
-    decode_w = dlg_window_new("Ethereal: Decode As");
-    SIGNAL_CONNECT(decode_w, "delete_event", decode_delete_cb, NULL);
-    SIGNAL_CONNECT(decode_w, "destroy", decode_destroy_cb, NULL);
+    decode_w = dlg_window_new("Wireshark: Decode As");
+    /* Provide a minimum of a couple of rows worth of data */
+    gtk_window_set_default_size(GTK_WINDOW(decode_w), -1, E_DECODE_MIN_HEIGHT);
 
     /* Container for each row of widgets */
     main_vb = gtk_vbox_new(FALSE, 2);
-    gtk_container_border_width(GTK_CONTAINER(main_vb), 5);
+    gtk_container_set_border_width(GTK_CONTAINER(main_vb), 5);
     gtk_container_add(GTK_CONTAINER(decode_w), main_vb);
 
     /* First row - Buttons and Notebook */
-    {
-       format_hb = gtk_hbox_new(FALSE, 5);
-       gtk_box_pack_start(GTK_BOX(main_vb), format_hb, TRUE, TRUE, 10);
+    format_hb = gtk_hbox_new(FALSE, 5);
+    gtk_box_pack_start(GTK_BOX(main_vb), format_hb, TRUE, TRUE, 10);
 
-       button_vb = decode_add_yes_no();
-       gtk_box_pack_start(GTK_BOX(format_hb), button_vb, TRUE, TRUE, 10);
+    button_vb = decode_add_yes_no();
+    gtk_box_pack_start(GTK_BOX(format_hb), button_vb, TRUE, TRUE, 10);
 
-       decode_add_notebook(format_hb);
-    }
-
-    /* Button row: OK, Apply and cancel buttons */
-    bbox = gtk_hbutton_box_new();
-    gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_END);
-    gtk_button_box_set_spacing(GTK_BUTTON_BOX(bbox), 5);
-    gtk_box_pack_start(GTK_BOX(main_vb), bbox, FALSE, FALSE, 10);
-
-#if GTK_MAJOR_VERSION < 2
-    ok_bt = gtk_button_new_with_label("OK");
+    button = gtk_button_new_with_label("Show Current");
+    g_signal_connect(button, "clicked", G_CALLBACK(decode_show_cb), NULL);
+#if GTK_CHECK_VERSION(2,18,0)
+    gtk_widget_set_can_default(button, TRUE);
 #else
-    ok_bt = gtk_button_new_from_stock(GTK_STOCK_OK);
+    GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
 #endif
-    SIGNAL_CONNECT(ok_bt, "clicked", decode_ok_cb, decode_w);
-    GTK_WIDGET_SET_FLAGS(ok_bt, GTK_CAN_DEFAULT);
-    gtk_box_pack_start(GTK_BOX(bbox), ok_bt, FALSE, FALSE, 0);
-    gtk_widget_grab_default(ok_bt);
+    gtk_box_pack_start(GTK_BOX(button_vb), button, FALSE, FALSE, 0);
+       gtk_widget_set_tooltip_text(button, "Open a dialog showing the current settings.");
 
-#if GTK_MAJOR_VERSION < 2
-    apply_bt = gtk_button_new_with_label("Apply");
+    button = gtk_button_new_from_stock(GTK_STOCK_CLEAR);
+    g_signal_connect(button, "clicked", G_CALLBACK(decode_clear_cb), NULL);
+#if GTK_CHECK_VERSION(2,18,0)
+    gtk_widget_set_can_default(button, TRUE);
 #else
-    apply_bt = gtk_button_new_from_stock(GTK_STOCK_APPLY);
+    GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
 #endif
-    SIGNAL_CONNECT(apply_bt, "clicked", decode_apply_cb, decode_w);
-    GTK_WIDGET_SET_FLAGS(apply_bt, GTK_CAN_DEFAULT);
-    gtk_box_pack_start(GTK_BOX(bbox), apply_bt, FALSE, FALSE, 0);
+    gtk_box_pack_start(GTK_BOX(button_vb), button, FALSE, FALSE, 0);
+       gtk_widget_set_tooltip_text(button, "Clear ALL settings.");
 
-    button = gtk_button_new_with_label("Show Current");
-    SIGNAL_CONNECT(button, "clicked", decode_show_cb, decode_w);
-    GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
-    gtk_box_pack_start(GTK_BOX(bbox), button, FALSE, FALSE, 0);
+    decode_add_notebook(format_hb);
 
-#if GTK_MAJOR_VERSION < 2
-    cancel_bt = gtk_button_new_with_label("Cancel");
-#else
-    cancel_bt = gtk_button_new_from_stock(GTK_STOCK_CANCEL);
-#endif
-    SIGNAL_CONNECT(cancel_bt, "clicked", decode_cancel_cb, decode_w);
-    GTK_WIDGET_SET_FLAGS(cancel_bt, GTK_CAN_DEFAULT);
-    gtk_box_pack_start(GTK_BOX(bbox), cancel_bt, FALSE, FALSE, 0);
+    /* Button row */
+    bbox = dlg_button_row_new(GTK_STOCK_OK, GTK_STOCK_APPLY, GTK_STOCK_CLOSE, GTK_STOCK_HELP, NULL);
+    gtk_box_pack_start(GTK_BOX(main_vb), bbox, FALSE, FALSE, 0);
+    gtk_widget_show(bbox);
 
-    /*
-     * Catch the "key_press_event" signal in the window, so that
-     * we can catch the ESC key being pressed and act as if the
-     * "Cancel" button had been selected.
-     */
-    dlg_set_cancel(decode_w, cancel_bt);
+    ok_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_OK);
+    g_signal_connect(ok_bt, "clicked", G_CALLBACK(decode_ok_cb), decode_w);
+       gtk_widget_set_tooltip_text(ok_bt, "Apply current setting, close dialog and redissect packets.");
 
-    gtk_widget_show_all(decode_w);
-}
+    apply_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_APPLY);
+    g_signal_connect(apply_bt, "clicked", G_CALLBACK(decode_apply_cb), decode_w);
+       gtk_widget_set_tooltip_text(apply_bt, "Apply current setting, redissect packets and keep dialog open.");
 
+    close_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_CLOSE);
+    window_set_cancel_button(decode_w, close_bt, NULL);
+    g_signal_connect(close_bt, "clicked", G_CALLBACK(decode_close_cb), decode_w);
+       gtk_widget_set_tooltip_text(close_bt, "Close the dialog, don't redissect packets.");
 
-/*
- * Local Variables:
- * mode:c
- * c-basic-offset: 4
- * End:
- */
+    help_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_HELP);
+    g_signal_connect(help_bt, "clicked", G_CALLBACK(topic_cb), (gpointer)HELP_DECODE_AS_DIALOG);
+
+    gtk_widget_grab_default(ok_bt);
+
+    g_signal_connect(decode_w, "delete_event", G_CALLBACK(decode_delete_cb), NULL);
+    g_signal_connect(decode_w, "destroy", G_CALLBACK(decode_destroy_cb), NULL);
+
+    gtk_widget_show_all(decode_w);
+    window_present(decode_w);
+}