remove some warnings
[obnox/wireshark/wip.git] / gtk / decode_as_dlg.c
1 /* decode_as_dlg.c
2  *
3  * $Id$
4  *
5  * Routines to modify dissector tables on the fly.
6  *
7  * By David Hampton <dhampton@mac.com>
8  * Copyright 2001 David Hampton
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License
12  * as published by the Free Software Foundation; either version 2
13  * of the License, or (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
23  */
24
25 #ifdef HAVE_CONFIG_H
26 # include "config.h"
27 #endif
28
29 #include <gtk/gtk.h>
30 #include <string.h>
31
32 #include "decode_as_dlg.h"
33 #include "dlg_utils.h"
34 #include "globals.h"
35 #include "simple_dialog.h"
36 #include <epan/packet.h>
37 #include <epan/ipproto.h>
38 #include "gui_utils.h"
39 #include <epan/epan_dissect.h>
40 #include "compat_macros.h"
41 #include "decode_as_dcerpc.h"
42 #include "help_dlg.h"
43
44 #undef DEBUG
45
46 /**************************************************/
47 /*                Typedefs & Enums                */
48 /**************************************************/
49
50 /*
51  * Enum used to track which transport layer port menu item is
52  * currently selected in the dialog.  These items are labeled "source",
53  * "destination", and "source/destination".
54  */
55 enum srcdst_type {
56     /* The "source port" menu item is currently selected. */
57     E_DECODE_SPORT,
58     /* The "destination port" menu item is currently selected. */
59     E_DECODE_DPORT,
60     /* The "source/destination port" menu item is currently selected. */
61     E_DECODE_BPORT,
62     /* For SCTP only. This MUST be the last entry! */
63     E_DECODE_PPID
64 };
65
66 #define E_DECODE_MIN_HEIGHT 300
67 #define E_NOTEBOOK "notebook"
68
69 #define E_MENU_SRCDST "menu_src_dst"
70
71 #define E_PAGE_DPORT "dport"
72 #define E_PAGE_SPORT "sport"
73 #define E_PAGE_PPID  "ppid"
74
75 /*
76  * Columns for a "Display" list
77  */
78 #define E_LIST_D_TABLE      0
79 #define E_LIST_D_SELECTOR   1
80 #define E_LIST_D_INITIAL    2
81 #define E_LIST_D_CURRENT    3
82 #define E_LIST_D_MAX        E_LIST_D_CURRENT
83 #define E_LIST_D_COLUMNS   (E_LIST_D_MAX + 1)
84
85 /**************************************************/
86 /*             File Global Variables              */
87 /**************************************************/
88
89 /*
90  * Keep a static pointer to the current "Decode As" window.  This is
91  * kept so that if somebody tries to do "Tools:Decode As" while
92  * there's already a "Decode As" window up, we just pop up the
93  * existing one, rather than creating a new one.
94  */
95 static GtkWidget *decode_w = NULL;
96
97 /*
98  * A static pointer to the current "Decode As:Show" window.  This is
99  * kept so that if somebody tries to do clock the "Show Current"
100  * button or select the "Display:User Specified Decodes" menu item
101  * while there's already a "Decode As:Show" window up, we just pop up
102  * the existing one, rather than creating a new one.
103  */
104 static GtkWidget *decode_show_w = NULL;
105
106 /*
107  * A list of the dialog items that only have meaning when the user has
108  * selected the "Decode" radio button.  When the "Do not decode"
109  * button is selected these items should be dimmed.
110  */
111 GSList *decode_dimmable = NULL;
112
113 /*
114  * Remember the "action" radio button that is currently selected in
115  * the dialog.  This value is initialized when the dialog is created,
116  * modified in a callback routine, and read in the routine that
117  * handles a click in the "OK" button for the dialog.
118  */
119 enum action_type        requested_action = -1;
120
121
122 /**************************************************/
123 /*            Global Functions                    */
124 /**************************************************/
125
126 /* init this module */
127 void decode_as_init(void) {
128
129     decode_dcerpc_init();
130 }
131
132 /**************************************************/
133 /*            Reset Changed Dissectors            */
134 /**************************************************/
135
136 /*
137  * Data structure for tracking which dissector need to be reset.  This
138  * structure is necessary as a hash table entry cannot be removed
139  * while a g_hash_table_foreach walk is in progress.
140  */
141 struct dissector_delete_item {
142     /* The name of the dissector table */
143     const gchar *ddi_table_name;
144     /* The type of the selector in that dissector table */
145     ftenum_t ddi_selector_type;
146     /* The selector in the dissector table */
147     union {
148         guint   sel_uint;
149         char    *sel_string;
150     } ddi_selector;
151 };
152
153 /*
154  * A typedef for the data structure to track the original dissector
155  * used for any given port on any given protocol.
156  */
157 typedef struct dissector_delete_item dissector_delete_item_t;
158
159 /*
160  * A list of dissectors that need to be reset.
161  */
162 GSList *dissector_reset_list = NULL;
163
164 /*
165  * This routine creates one entry in the list of protocol dissector
166  * that need to be reset. It is called by the g_hash_table_foreach
167  * routine once for each changed entry in a dissector table.
168  * Unfortunately it cannot delete the entry immediately as this screws
169  * up the foreach function, so it builds a list of dissectors to be
170  * reset once the foreach routine finishes.
171  *
172  * @param table_name The table name in which this dissector is found.
173  *
174  * @param key A pointer to the key for this entry in the dissector
175  * hash table.  This is generally the numeric selector of the
176  * protocol, i.e. the ethernet type code, IP port number, TCP port
177  * number, etc.
178  *
179  * @param value A pointer to the value for this entry in the dissector
180  * hash table.  This is an opaque pointer that can only be handed back
181  * to routine in the file packet.c - but it's unused.
182  *
183  * @param user_data Unused.
184  */
185 static void
186 decode_build_reset_list (gchar *table_name, ftenum_t selector_type,
187                          gpointer key, gpointer value _U_,
188                          gpointer user_data _U_)
189 {
190     dissector_delete_item_t *item;
191
192     item = g_malloc(sizeof(dissector_delete_item_t));
193     item->ddi_table_name = table_name;
194     item->ddi_selector_type = selector_type;
195     switch (selector_type) {
196
197     case FT_UINT8:
198     case FT_UINT16:
199     case FT_UINT24:
200     case FT_UINT32:
201         item->ddi_selector.sel_uint = GPOINTER_TO_UINT(key);
202         break;
203
204     case FT_STRING:
205     case FT_STRINGZ:
206         item->ddi_selector.sel_string = key;
207         break;
208
209     default:
210         g_assert_not_reached();
211     }
212     dissector_reset_list = g_slist_prepend(dissector_reset_list, item);
213 }
214
215
216 /**************************************************/
217 /*             Show Changed Dissectors            */
218 /**************************************************/
219
220 #if GTK_MAJOR_VERSION >= 2
221 #define SORT_ALPHABETICAL 0
222
223 static gint
224 sort_iter_compare_func (GtkTreeModel *model,
225 GtkTreeIter *a,
226 GtkTreeIter *b,
227 gpointer userdata)
228 {
229     gint sortcol = GPOINTER_TO_INT(userdata);
230     gint ret = 0;
231     switch (sortcol)
232     {
233         case SORT_ALPHABETICAL:
234         {
235         gchar *name1, *name2;
236         gtk_tree_model_get(model, a, 0, &name1, -1);
237         gtk_tree_model_get(model, b, 0, &name2, -1);
238         if (name1 == NULL || name2 == NULL)
239         {
240             if (name1 == NULL && name2 == NULL)
241                 break; /* both equal => ret = 0 */
242             ret = (name1 == NULL) ? -1 : 1;
243         }
244         else
245         {
246             ret = g_ascii_strcasecmp(name1,name2);
247         }
248         g_free(name1);
249         g_free(name2);
250         }
251         break;
252         default:
253         g_return_val_if_reached(0);
254     }
255     return ret;
256 }
257 #endif
258
259
260 void
261 decode_add_to_show_list (
262 gpointer list_data, 
263 const gchar *table_name, 
264 gchar *selector_name, 
265 const gchar *initial_proto_name, 
266 const gchar *current_proto_name)
267 {
268     const gchar     *text[E_LIST_D_COLUMNS];
269 #if GTK_MAJOR_VERSION < 2
270     GtkCList  *clist;
271     gint       row;
272 #else
273     GtkListStore *store;
274     GtkTreeIter   iter;
275 #endif
276
277 #if GTK_MAJOR_VERSION < 2
278     clist = (GtkCList *)list_data;
279 #else
280     store = (GtkListStore *)list_data;
281 #endif
282
283     text[E_LIST_D_TABLE] = table_name;
284     text[E_LIST_D_SELECTOR] = selector_name;
285     text[E_LIST_D_INITIAL] = initial_proto_name;
286     text[E_LIST_D_CURRENT] = current_proto_name;
287 #if GTK_MAJOR_VERSION < 2
288     row = gtk_clist_prepend(clist, (gchar **) text);
289 #else
290     gtk_list_store_append(store, &iter);
291     gtk_list_store_set(store, &iter, E_LIST_D_TABLE, text[E_LIST_D_TABLE],
292                        E_LIST_D_SELECTOR, text[E_LIST_D_SELECTOR],
293                        E_LIST_D_INITIAL, text[E_LIST_D_INITIAL],
294                        E_LIST_D_CURRENT, text[E_LIST_D_CURRENT], -1);
295 #endif
296 }
297
298
299 /*
300  * This routine creates one entry in the list of protocol dissector
301  * that have been changed.  It is called by the g_hash_foreach routine
302  * once for each changed entry in a dissector table.
303  *
304  * @param table_name The table name in which this dissector is found.
305  *
306  * @param key A pointer to the key for this entry in the dissector
307  * hash table.  This is generally the numeric selector of the
308  * protocol, i.e. the ethernet type code, IP port number, TCP port
309  * number, etc.
310  *
311  * @param value A pointer to the value for this entry in the dissector
312  * hash table.  This is an opaque pointer that can only be handed back
313  * to routine in the file packet.c
314  *
315  * @param user_data A pointer to the list in which this information
316  * should be stored.
317  */
318 static void
319 decode_build_show_list (gchar *table_name, ftenum_t selector_type,
320                         gpointer key, gpointer value, gpointer user_data)
321 {
322     dissector_handle_t current, initial;
323     const gchar *current_proto_name, *initial_proto_name;
324     gchar       *selector_name;
325     gchar        string1[20];
326
327     g_assert(user_data);
328     g_assert(value);
329
330     current = dtbl_entry_get_handle(value);
331     if (current == NULL)
332         current_proto_name = "(none)";
333     else
334         current_proto_name = dissector_handle_get_short_name(current);
335     initial = dtbl_entry_get_initial_handle(value);
336     if (initial == NULL)
337         initial_proto_name = "(none)";
338     else
339         initial_proto_name = dissector_handle_get_short_name(initial);
340
341     switch (selector_type) {
342
343     case FT_UINT8:
344     case FT_UINT16:
345     case FT_UINT24:
346     case FT_UINT32:
347         switch (get_dissector_table_base(table_name)) {
348
349         case BASE_DEC:
350             g_snprintf(string1, sizeof(string1), "%u", GPOINTER_TO_UINT(key));
351             break;
352
353         case BASE_HEX:
354             switch (get_dissector_table_selector_type(table_name)) {
355
356             case FT_UINT8:
357                 g_snprintf(string1, sizeof(string1), "0x%02x", GPOINTER_TO_UINT(key));
358                 break;
359
360             case FT_UINT16:
361                 g_snprintf(string1, sizeof(string1), "0x%04x", GPOINTER_TO_UINT(key));
362                 break;
363
364             case FT_UINT24:
365                 g_snprintf(string1, sizeof(string1), "0x%06x", GPOINTER_TO_UINT(key));
366                 break;
367
368             case FT_UINT32:
369                 g_snprintf(string1, sizeof(string1), "0x%08x", GPOINTER_TO_UINT(key));
370                 break;
371
372             default:
373                 g_assert_not_reached();
374                 break;
375             }
376             break;
377
378         case BASE_OCT:
379             g_snprintf(string1, sizeof(string1), "%#o", GPOINTER_TO_UINT(key));
380             break;
381         }
382         selector_name = string1;
383         break;
384
385     case FT_STRING:
386     case FT_STRINGZ:
387         selector_name = key;
388         break;
389
390     default:
391         g_assert_not_reached();
392         selector_name = NULL;
393         break;
394     }
395
396     decode_add_to_show_list (
397         user_data, 
398         get_dissector_table_ui_name(table_name),
399         selector_name, 
400         initial_proto_name, 
401         current_proto_name);
402 }
403
404
405 /* clear all settings */
406 static void
407 decode_clear_all(void)
408 {
409     dissector_delete_item_t *item;
410     GSList *tmp;
411
412     dissector_all_tables_foreach_changed(decode_build_reset_list, NULL);
413
414     for (tmp = dissector_reset_list; tmp; tmp = g_slist_next(tmp)) {
415         item = tmp->data;
416         switch (item->ddi_selector_type) {
417
418         case FT_UINT8:
419         case FT_UINT16:
420         case FT_UINT24:
421         case FT_UINT32:
422             dissector_reset(item->ddi_table_name, item->ddi_selector.sel_uint);
423             break;
424
425         case FT_STRING:
426         case FT_STRINGZ:
427             dissector_reset_string(item->ddi_table_name,
428                                    item->ddi_selector.sel_string);
429             break;
430
431         default:
432             g_assert_not_reached();
433         }
434         g_free(item);
435     }
436     g_slist_free(dissector_reset_list);
437     dissector_reset_list = NULL;
438
439     decode_dcerpc_reset_all();
440
441     cf_redissect_packets(&cfile);
442 }
443
444
445 /*
446  * This routine is called when the user clicks the "OK" button in
447  * the "Decode As:Show..." dialog window.  This routine destroys the
448  * dialog box and performs other housekeeping functions.
449  *
450  * @param GtkWidget * A pointer to the "OK" button.
451  *
452  * @param gpointer A pointer to the dialog window.
453  */
454 static void
455 decode_show_ok_cb (GtkWidget *ok_bt _U_, gpointer parent_w)
456 {
457     window_destroy(GTK_WIDGET(parent_w));
458 }
459
460
461 /*
462  * This routine is called when the user clicks the "Clear" button in
463  * the "Decode As:Show..." dialog window.  This routine resets all the
464  * dissector values and then destroys the dialog box and performs
465  * other housekeeping functions.
466  *
467  * @param GtkWidget * A pointer to the "Clear" button.
468  *
469  * @param gpointer A pointer to the dialog window.
470  */
471 static void
472 decode_show_clear_cb (GtkWidget *clear_bt _U_, gpointer parent_w)
473 {
474     decode_clear_all();
475
476     window_destroy(GTK_WIDGET(parent_w));
477 }
478
479
480 /*
481  * This routine is called when the user clicks the X at the top right end in
482  * the "Decode As:Show..." dialog window.  This routine simply calls the
483  * ok routine as if the user had clicked the ok button.
484  *
485  * @param GtkWidget * A pointer to the dialog box.
486  *
487  * @param gpointer Unknown
488  */
489 static gboolean
490 decode_show_delete_cb (GtkWidget *decode_w _U_, gpointer dummy _U_)
491 {
492     decode_show_ok_cb(NULL, decode_show_w);
493     return FALSE;
494 }
495
496
497 /*
498  * This routine is called at the destruction of the "Decode As:Show"
499  * dialog box.  It clears the pointer maintained by this file, so that
500  * the next time the user clicks the "Decode As:Show" button a new
501  * dialog box will be created.
502  *
503  * @param GtkWidget * A pointer to the dialog box.
504  *
505  * @param gpointer Unknown
506  */
507 static void
508 decode_show_destroy_cb (GtkWidget *win _U_, gpointer user_data _U_)
509 {
510     /* Note that we no longer have a "Decode As:Show" dialog box. */
511     decode_show_w = NULL;
512 }
513
514
515 /*
516  * This routine creates the "Decode As:Show" dialog box. This dialog box
517  * shows the user which protocols have had their dissectors changed.
518  *
519  * @param w Unknown
520  * @param data Unknown
521  */
522 void
523 decode_show_cb (GtkWidget * w _U_, gpointer data _U_)
524 {
525     GtkWidget         *main_vb, *bbox, *ok_bt, *clear_bt, *help_bt, *scrolled_window;
526     const gchar       *titles[E_LIST_D_COLUMNS] = {
527         "Table", "Value", "Initial", "Current"
528     };
529     gint               column;
530 #if GTK_MAJOR_VERSION < 2
531     GtkCList          *list;
532 #else
533     GtkListStore      *store;
534     GtkTreeView       *list;
535     GtkCellRenderer   *renderer;
536     GtkTreeViewColumn *tc;
537     GtkTreeIter        iter;
538 #endif
539
540     if (decode_show_w != NULL) {
541         /* There's already a "Decode As" dialog box; reactivate it. */
542         reactivate_window(decode_show_w);
543         return;
544     }
545
546     decode_show_w = dlg_window_new("Wireshark: Decode As: Show");
547         /* Provide a minimum of a couple of rows worth of data */
548     gtk_window_set_default_size(GTK_WINDOW(decode_show_w), -1, E_DECODE_MIN_HEIGHT);
549
550     /* Container for each row of widgets */
551     main_vb = gtk_vbox_new(FALSE, 2);
552     gtk_container_border_width(GTK_CONTAINER(main_vb), 5);
553     gtk_container_add(GTK_CONTAINER(decode_show_w), main_vb);
554
555     {
556         /* Initialize list */
557 #if GTK_MAJOR_VERSION < 2
558         list = GTK_CLIST(gtk_clist_new_with_titles(E_LIST_D_COLUMNS, (gchar **) titles));
559         gtk_clist_column_titles_passive(list);
560         for (column = 0; column < E_LIST_D_COLUMNS; column++)
561             gtk_clist_set_column_auto_resize(list, column, TRUE);
562         gtk_clist_set_selection_mode(list, GTK_SELECTION_EXTENDED);
563 #else
564         store = gtk_list_store_new(E_LIST_D_COLUMNS, G_TYPE_STRING,
565                                    G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
566         list = GTK_TREE_VIEW(tree_view_new(GTK_TREE_MODEL(store)));
567         gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(list), TRUE);
568         gtk_tree_view_set_headers_clickable(GTK_TREE_VIEW(list), FALSE);
569         gtk_tree_selection_set_mode(gtk_tree_view_get_selection(list),
570                                     GTK_SELECTION_MULTIPLE);
571
572         for (column = 0; column < E_LIST_D_COLUMNS; column++) {
573             renderer = gtk_cell_renderer_text_new();
574             tc = gtk_tree_view_column_new_with_attributes(titles[column],
575                                                           renderer, "text",
576                                                           column, NULL);
577             gtk_tree_view_column_set_sizing(tc, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
578             gtk_tree_view_append_column(list, tc);
579         }
580 #endif
581
582         /* Add data */
583 #if GTK_MAJOR_VERSION < 2
584         dissector_all_tables_foreach_changed(decode_build_show_list, list);
585         gtk_clist_sort(list);
586     decode_dcerpc_add_show_list(list);
587 #else
588         dissector_all_tables_foreach_changed(decode_build_show_list, store);
589         g_object_unref(G_OBJECT(store));
590     decode_dcerpc_add_show_list(store);
591 #endif
592
593         /* Put clist into a scrolled window */
594         scrolled_window = scrolled_window_new(NULL, NULL);
595     /* this will result to set the width of the dialog to the required size */
596         gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window),
597                                        GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
598 #if GTK_MAJOR_VERSION >= 2
599     gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled_window), 
600                                    GTK_SHADOW_IN);
601 #endif
602         gtk_container_add(GTK_CONTAINER(scrolled_window),
603                           GTK_WIDGET(list));
604         gtk_box_pack_start(GTK_BOX(main_vb), scrolled_window, TRUE, TRUE, 0);
605     }
606
607     /* Button row */
608     if(topic_available(HELP_DECODE_AS_SHOW_DIALOG)) {
609         bbox = dlg_button_row_new(GTK_STOCK_OK, GTK_STOCK_CLEAR, GTK_STOCK_HELP, NULL);
610     } else {
611         bbox = dlg_button_row_new(GTK_STOCK_OK, GTK_STOCK_CLEAR, NULL);
612     }
613     gtk_box_pack_start(GTK_BOX(main_vb), bbox, FALSE, FALSE, 0);
614     gtk_widget_show(bbox);
615
616     ok_bt = OBJECT_GET_DATA(bbox, GTK_STOCK_OK);
617     SIGNAL_CONNECT(ok_bt, "clicked", decode_show_ok_cb, decode_show_w);
618     
619     clear_bt = OBJECT_GET_DATA(bbox, GTK_STOCK_CLEAR);
620     SIGNAL_CONNECT(clear_bt, "clicked", decode_show_clear_cb, decode_show_w);
621
622     if(topic_available(HELP_DECODE_AS_SHOW_DIALOG)) {
623         help_bt = OBJECT_GET_DATA(bbox, GTK_STOCK_HELP);
624         SIGNAL_CONNECT(help_bt, "clicked", topic_cb, HELP_DECODE_AS_SHOW_DIALOG);
625     }
626
627     /* set ok as default, this button won't change anything */
628     window_set_cancel_button(decode_show_w, ok_bt, NULL);
629
630     SIGNAL_CONNECT(decode_show_w, "delete_event", decode_show_delete_cb, NULL);
631     SIGNAL_CONNECT(decode_show_w, "destroy", decode_show_destroy_cb, NULL);
632     
633 #if GTK_MAJOR_VERSION < 2
634     gtk_widget_set_sensitive(clear_bt, (list->rows != 0));
635 #else
636     gtk_widget_set_sensitive(clear_bt,
637                              gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter));
638 #endif
639
640     gtk_widget_show_all(decode_show_w);
641     window_present(decode_show_w);
642 }
643
644
645 /**************************************************/
646 /*         Modify the dissector routines          */
647 /**************************************************/
648
649 /*
650  * Modify a single dissector.  This routine first takes care of
651  * updating the internal table of original protocol/port/dissector
652  * combinations by adding a new entry (or removing an existing entry
653  * if the value is being set back to its default).  This routine then
654  * performs the actual modification to the packet dissector tables.
655  *
656  * @param s Pointer to a string buffer.  This buffer is used to build
657  * up a message indicating which ports have had their dissector
658  * changed. This output will be displayed all at once after all
659  * dissectors have been modified.
660  *
661  * @param table_name The table name in which the dissector should be
662  * modified.
663  *
664  * @param selector An enum value indication which selector value
665  * (i.e. IP protocol number, TCP port number, etc.)is to be changed.
666  *
667  * @param list The List in which all the selection information can
668  * be found.
669  *
670  * @return gchar * Pointer to the next free location in the string
671  * buffer.
672  */
673 static void
674 decode_change_one_dissector(gchar *table_name, guint selector, GtkWidget *list)
675 {
676     dissector_handle_t handle;
677     gchar              *abbrev;
678 #if GTK_MAJOR_VERSION < 2
679     gint               row;
680 #else
681     GtkTreeSelection  *selection;
682     GtkTreeModel      *model;
683     GtkTreeIter        iter;
684 #endif
685
686 #if GTK_MAJOR_VERSION < 2
687     if (!GTK_CLIST(list)->selection)
688     {
689         abbrev = NULL;
690         handle = NULL;
691     } else {
692         row = GPOINTER_TO_INT(GTK_CLIST(list)->selection->data);
693         handle = gtk_clist_get_row_data(GTK_CLIST(list), row);
694         gtk_clist_get_text(GTK_CLIST(list), row, E_LIST_S_PROTO_NAME, &abbrev);
695     }
696 #else
697     selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(list));
698     if (gtk_tree_selection_get_selected(selection, &model, &iter) == FALSE)
699     {
700         abbrev = NULL;
701         handle = NULL;
702     } else {
703         gtk_tree_model_get(model, &iter, E_LIST_S_PROTO_NAME, &abbrev,
704                            E_LIST_S_TABLE+1, &handle, -1);
705     }
706 #endif
707
708     if (abbrev != NULL && strcmp(abbrev, "(default)") == 0) {
709         dissector_reset(table_name, selector);
710     } else {
711         dissector_change(table_name, selector, handle);
712     }
713 #if GTK_MAJOR_VERSION >= 2
714     if (abbrev != NULL)
715         g_free(abbrev);
716 #endif
717 }
718
719
720 /**************************************************/
721 /* Action routines for the "Decode As..." dialog  */
722 /*   - called when the OK button pressed          */
723 /*   - one per notebook page                      */
724 /**************************************************/
725
726
727 #ifdef DEBUG
728 /*
729  * Print debugging information about clist selection.  Extract all
730  * information from the clist entry that was selected and print it to
731  * a dialog window.
732  *
733  * @param clist The clist to dump.
734  *
735  * @param leadin A string to print at the start of each line.
736  */
737 static void
738 decode_debug (GtkCList *clist, gchar *leadin)
739 {
740     gchar *string, *text[E_LIST_S_COLUMNS];
741     dissector_handle_t handle;
742     gint row;
743
744     if (clist->selection) {
745         row = GPOINTER_TO_INT(clist->selection->data);
746         gtk_clist_get_text(clist, row, E_LIST_S_PROTO_NAME, &text[E_LIST_S_PROTO_NAME]);
747         gtk_clist_get_text(clist, row, E_LIST_S_TABLE, &text[E_LIST_S_TABLE]);
748         handle = gtk_clist_get_row_data(clist, row);
749         string = g_strdup_printf("%s clist row %d: <put handle here>, name %s, table %s",
750                 leadin, row, text[E_LIST_S_PROTO_NAME],
751                 text[E_LIST_S_TABLE]);
752     } else {
753         string = g_strdup_printf("%s clist row (none), aka do not decode", leadin);
754     }
755     simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK, string);
756     g_free(string);
757 }
758 #endif
759
760
761 /*
762  * This routine is called when the user clicks the "OK" button in the
763  * "Decode As..." dialog window and a 'simple' page is foremost.
764  * This routine takes care of making any changes requested to the
765  * dissector tables.  This routine is currently used for IP and
766  * Ethertypes.  Any 'single change' notebook page can use this
767  * routine.
768  *
769  * @param notebook_pg A pointer to the "network" notebook page.
770  */
771 static void
772 decode_simple (GtkWidget *notebook_pg)
773 {
774     GtkWidget *list;
775 #ifdef DEBUG
776     gchar *string;
777 #endif
778     gchar *table_name;
779     guint value;
780
781     list = OBJECT_GET_DATA(notebook_pg, E_PAGE_LIST);
782     if (requested_action == E_DECODE_NO)
783 #if GTK_MAJOR_VERSION < 2
784         gtk_clist_unselect_all(GTK_CLIST(list));
785 #else
786         gtk_tree_selection_unselect_all(gtk_tree_view_get_selection(GTK_TREE_VIEW(list)));
787 #endif
788
789 #ifdef DEBUG
790     string = OBJECT_GET_DATA(notebook_pg, E_PAGE_TITLE);
791     decode_debug(GTK_CLIST(list), string);
792 #endif
793
794     table_name = OBJECT_GET_DATA(notebook_pg, E_PAGE_TABLE);
795     value = GPOINTER_TO_UINT(OBJECT_GET_DATA(notebook_pg, E_PAGE_VALUE));
796     decode_change_one_dissector(table_name, value, list);
797 }
798
799
800 /*
801  * This routine is called when the user clicks the "OK" button in the
802  * "Decode As..." dialog window and the transport page is foremost.
803  * This routine takes care of making any changes requested to the TCP
804  * or UDP dissector tables.
805  *
806  * @param notebook_pg A pointer to the "transport" notebook page.
807  */
808 static void
809 decode_transport(GtkWidget *notebook_pg)
810 {
811     GtkWidget *menu, *menuitem;
812     GtkWidget *list;
813     gchar *table_name;
814     gint requested_srcdst, requested_port, ppid;
815     gpointer portp;
816
817     list = OBJECT_GET_DATA(notebook_pg, E_PAGE_LIST);
818     if (requested_action == E_DECODE_NO)
819 #if GTK_MAJOR_VERSION < 2
820         gtk_clist_unselect_all(GTK_CLIST(list));
821 #else
822         gtk_tree_selection_unselect_all(gtk_tree_view_get_selection(GTK_TREE_VIEW(list)));
823 #endif
824
825     menu = OBJECT_GET_DATA(notebook_pg, E_MENU_SRCDST);
826
827     menuitem = gtk_menu_get_active(GTK_MENU(menu));
828     requested_srcdst = GPOINTER_TO_INT(OBJECT_GET_DATA(menuitem, "user_data"));
829
830 #ifdef DEBUG
831     string = OBJECT_GET_DATA(notebook_pg, E_PAGE_TITLE);
832     decode_debug(GTK_CLIST(list), string);
833 #endif
834
835     table_name = OBJECT_GET_DATA(notebook_pg, E_PAGE_TABLE);
836     if (requested_srcdst >= E_DECODE_PPID) {
837         if (requested_srcdst == E_DECODE_PPID)
838            ppid = 0;
839         else
840            if (requested_srcdst - E_DECODE_PPID - 1 < MAX_NUMBER_OF_PPIDS)
841              ppid = cfile.edt->pi.ppid[requested_srcdst - E_DECODE_PPID - 1];
842            else 
843              return;
844         decode_change_one_dissector(table_name, ppid, list);
845         return;
846     }
847     if (requested_srcdst != E_DECODE_DPORT) {
848         portp = OBJECT_GET_DATA(notebook_pg, E_PAGE_SPORT);
849         if (portp != NULL) {
850             requested_port = GPOINTER_TO_INT(portp);
851             decode_change_one_dissector(table_name, requested_port, list);
852         }
853     }
854     if (requested_srcdst != E_DECODE_SPORT) {
855         portp = OBJECT_GET_DATA(notebook_pg, E_PAGE_DPORT);
856         if (portp != NULL) {
857             requested_port = GPOINTER_TO_INT(portp);
858             decode_change_one_dissector(table_name, requested_port, list);
859         }
860     }
861 }
862
863
864 /**************************************************/
865 /*      Signals from the "Decode As..." dialog    */
866 /**************************************************/
867
868 /*
869  * This routine is called when the user clicks the "OK" button in the
870  * "Decode As..." dialog window.  This routine calls various helper
871  * routines to set/clear dissector values as requested by the user.
872  * These routines accumulate information on what actions they have
873  * taken, and this summary information is printed by this routine.
874  * This routine then destroys the dialog box and performs other
875  * housekeeping functions.
876  *
877  * @param ok_bt A pointer to the "OK" button.
878  *
879  * @param parent_w A pointer to the dialog window.
880  */
881 static void
882 decode_ok_cb (GtkWidget *ok_bt _U_, gpointer parent_w)
883 {
884     GtkWidget *notebook, *notebook_pg;
885     void (* func)(GtkWidget *);
886     gint page_num;
887     void *binding = NULL;
888
889     /* Call the right routine for the page that was currently in front. */
890     notebook =  OBJECT_GET_DATA(parent_w, E_NOTEBOOK);
891     page_num = gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook));
892     notebook_pg = gtk_notebook_get_nth_page(GTK_NOTEBOOK(notebook), page_num);
893
894     func = OBJECT_GET_DATA(notebook_pg, E_PAGE_ACTION);
895     func(notebook_pg);
896
897     /* Now destroy the "Decode As" dialog. */
898     notebook_pg = OBJECT_GET_DATA(parent_w, E_PAGE_DCERPC);
899     if(notebook_pg) {
900         binding = OBJECT_GET_DATA(notebook_pg, E_PAGE_BINDING);
901     }
902     if(binding) {
903         decode_dcerpc_binding_free(binding);    
904     }
905     window_destroy(GTK_WIDGET(parent_w));
906     g_slist_free(decode_dimmable);
907     decode_dimmable = NULL;
908
909     cf_redissect_packets(&cfile);
910 }
911
912 /*
913  * This routine is called when the user clicks the "Apply" button in the
914  * "Decode As..." dialog window.  This routine calls various helper
915  * routines to set/clear dissector values as requested by the user.
916  * These routines accumulate information on what actions they have
917  * taken, and this summary information is printed by this routine.
918  *
919  * @param apply_bt A pointer to the "Apply" button.
920  *
921  * @param parent_w A pointer to the dialog window.
922  */
923 static void
924 decode_apply_cb (GtkWidget *apply_bt _U_, gpointer parent_w)
925 {
926     GtkWidget *notebook, *notebook_pg;
927     void (* func)(GtkWidget *);
928     gint page_num;
929
930     /* Call the right routine for the page that was currently in front. */
931     notebook =  OBJECT_GET_DATA(parent_w, E_NOTEBOOK);
932     page_num = gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook));
933     notebook_pg = gtk_notebook_get_nth_page(GTK_NOTEBOOK(notebook), page_num);
934
935     func = OBJECT_GET_DATA(notebook_pg, E_PAGE_ACTION);
936     func(notebook_pg);
937
938     cf_redissect_packets(&cfile);
939 }
940
941 /*
942  * This routine is called when the user clicks the "Close" button in
943  * the "Decode As..." dialog window.  This routine then destroys the
944  * dialog box and performs other housekeeping functions.
945  *
946  * @param close_bt A pointer to the "Close" button.
947  *
948  * @param parent_w A pointer to the dialog window.
949  */
950 static void
951 decode_close_cb (GtkWidget *close_bt _U_, gpointer parent_w)
952 {
953     GtkWidget *notebook_pg = NULL;
954     void *binding = NULL;
955
956
957     notebook_pg = OBJECT_GET_DATA(parent_w, E_PAGE_DCERPC);
958     if(notebook_pg) {
959         binding = OBJECT_GET_DATA(notebook_pg, E_PAGE_BINDING);
960     }
961     if(binding) {
962         decode_dcerpc_binding_free(binding);
963     }
964     window_destroy(GTK_WIDGET(parent_w));
965     g_slist_free(decode_dimmable);
966     decode_dimmable = NULL;
967 }
968
969
970 /*
971  * This routine is called when the user clicks the "Close" button in
972  * the "Decode As..." dialog window.  This routine simply calls the
973  * close routine as if the user had clicked the close button instead
974  * of the close button.
975  *
976  * @param decode_w A pointer to the dialog box.
977  *
978  * @param dummy Unknown
979  */
980 static gboolean
981 decode_delete_cb (GtkWidget *decode_w, gpointer dummy _U_)
982 {
983     decode_close_cb(NULL, decode_w);
984     return FALSE;
985 }
986
987
988 /*
989  * This routine is called at the destruction of the "Decode As..."
990  * dialog box.  It clears the pointer maintained by this file, so that
991  * the next time the user selects the "Decode As..." menu item a new
992  * dialog box will be created.
993  *
994  * @param decode_w A pointer to the dialog box.
995  *
996  * @param user_data Unknown
997  *
998  * @return void
999  */
1000 static void
1001 decode_destroy_cb (GtkWidget *win _U_, gpointer user_data _U_)
1002 {
1003     /* Note that we no longer have a "Decode As" dialog box. */
1004     decode_w = NULL;
1005 }
1006
1007
1008 /*
1009  * This routine is called when the user clicks the "Clear" button in
1010  * the "Decode As..." dialog window.  This routine resets all the
1011  * dissector values and performs other housekeeping functions.
1012  *
1013  * @param GtkWidget * A pointer to the "Clear" button.
1014  * @param gpointer A pointer to the dialog window.
1015  */
1016 static void
1017 decode_clear_cb(GtkWidget *clear_bt _U_, gpointer parent_w _U_)
1018 {
1019     decode_clear_all();
1020 }
1021
1022
1023
1024 /**************************************************/
1025 /*          Dialog setup - radio buttons          */
1026 /**************************************************/
1027
1028 /*
1029  * Update the requested action field of the dialog.  This routine is
1030  * called by GTK when either of the two radio buttons in the dialog is
1031  * clicked.
1032  *
1033  * @param w The radio button that was clicked.
1034  *
1035  * @param data The enum value assigned to this radio button.  This
1036  * will be either E_DECODE_YES or E_DECODE_NO
1037  */
1038 static void
1039 decode_update_action (GtkWidget *w _U_, gpointer data)
1040 {
1041     GSList *tmp;
1042     gboolean enable;
1043
1044     requested_action = GPOINTER_TO_INT(data);
1045     enable = (requested_action == E_DECODE_YES);
1046     for (tmp = decode_dimmable; tmp; tmp = g_slist_next(tmp)) {
1047         gtk_widget_set_sensitive(tmp->data, enable);
1048     }
1049 }
1050
1051 /*
1052  * This routine is called to create the "Decode" and "Do not decode"
1053  * radio buttons.  These buttons are installed into a vbox, and set up
1054  * as a format group.
1055  *
1056  * @return GtkWidget * A pointer to the vbox containing the buttons
1057  */
1058 static GtkWidget *
1059 decode_add_yes_no (void)
1060 {
1061     GtkWidget   *format_vb, *radio_button;
1062     GSList      *format_grp;
1063
1064     format_vb = gtk_vbox_new(FALSE, 2);
1065
1066     radio_button = gtk_radio_button_new_with_label(NULL, "Decode");
1067     format_grp = gtk_radio_button_group(GTK_RADIO_BUTTON(radio_button));
1068     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio_button), TRUE);
1069     SIGNAL_CONNECT(radio_button, "clicked", decode_update_action,
1070                    GINT_TO_POINTER(E_DECODE_YES));
1071     gtk_box_pack_start(GTK_BOX(format_vb), radio_button, TRUE, TRUE, 0);
1072
1073     radio_button = gtk_radio_button_new_with_label(format_grp, "Do not decode");
1074     format_grp = gtk_radio_button_group(GTK_RADIO_BUTTON(radio_button));
1075     SIGNAL_CONNECT(radio_button, "clicked", decode_update_action,
1076                    GINT_TO_POINTER(E_DECODE_NO));
1077     gtk_box_pack_start(GTK_BOX(format_vb), radio_button, TRUE, TRUE, 0);
1078
1079     return(format_vb);
1080 }
1081
1082 /**************************************************/
1083 /*          Dialog setup - simple menus           */
1084 /**************************************************/
1085
1086 /*
1087  * This routine is called to pack an option menu into an aligment, so
1088  * that it doesn't expand vertically to fill up the space available to
1089  * it.
1090  *
1091  * @param optmenu A pointer to the option menu to be so packed.
1092  *
1093  * @return GtkWidget * A pointer to the newly created alignment.
1094  */
1095 static GtkWidget *
1096 decode_add_pack_menu (GtkWidget *optmenu)
1097 {
1098     GtkWidget *alignment;
1099
1100     alignment = gtk_alignment_new(0.0, 0.5, 0.0, 0.0);
1101     gtk_container_add(GTK_CONTAINER(alignment), optmenu);
1102
1103     return(alignment);
1104 }
1105
1106
1107 /*
1108  * This routine is called to add the transport port selection menu to
1109  * the dialog box.  This is a three choice menu: source, destination
1110  * and both.  The default choice for the menu is set to the source
1111  * port number of the currently selected packet.
1112  *
1113  * @param page A pointer notebook page that will contain all
1114  * widgets created by this routine.
1115  *
1116  * @return GtkWidget * A pointer to the newly created alignment into
1117  * which we've packed the newly created option menu.
1118  */
1119 static GtkWidget *
1120 decode_add_srcdst_menu (GtkWidget *page)
1121 {
1122     GtkWidget *optmenu, *menu, *menuitem, *alignment;
1123     gchar      tmp[100];
1124
1125     optmenu = gtk_option_menu_new();
1126     menu = gtk_menu_new();
1127     g_snprintf(tmp, 100, "source (%u)", cfile.edt->pi.srcport);
1128     menuitem = gtk_menu_item_new_with_label(tmp);
1129     OBJECT_SET_DATA(menuitem, "user_data", GINT_TO_POINTER(E_DECODE_SPORT));
1130     gtk_menu_append(GTK_MENU(menu), menuitem);
1131     gtk_widget_show(menuitem);  /* gtk_widget_show_all() doesn't show this */
1132
1133     g_snprintf(tmp, 100, "destination (%u)", cfile.edt->pi.destport);
1134     menuitem = gtk_menu_item_new_with_label(tmp);
1135     OBJECT_SET_DATA(menuitem, "user_data", GINT_TO_POINTER(E_DECODE_DPORT));
1136     gtk_menu_append(GTK_MENU(menu), menuitem);
1137     gtk_widget_show(menuitem);  /* gtk_widget_show_all() doesn't show this */
1138
1139     menuitem = gtk_menu_item_new_with_label("both");
1140     OBJECT_SET_DATA(menuitem, "user_data", GINT_TO_POINTER(E_DECODE_BPORT));
1141     gtk_menu_append(GTK_MENU(menu), menuitem);
1142     gtk_widget_show(menuitem);  /* gtk_widget_show_all() doesn't show this */
1143
1144     OBJECT_SET_DATA(page, E_MENU_SRCDST, menu);
1145     gtk_option_menu_set_menu(GTK_OPTION_MENU(optmenu), menu);
1146     OBJECT_SET_DATA(page, E_PAGE_SPORT, GINT_TO_POINTER(cfile.edt->pi.srcport));
1147     OBJECT_SET_DATA(page, E_PAGE_DPORT, GINT_TO_POINTER(cfile.edt->pi.destport));
1148
1149     alignment = decode_add_pack_menu(optmenu);
1150
1151     return(alignment);
1152 }
1153
1154 static GtkWidget *
1155 decode_add_ppid_menu (GtkWidget *page)
1156 {
1157     GtkWidget *optmenu, *menu, *menuitem;
1158     gchar      tmp[100];
1159     guint      number_of_ppid;
1160     
1161     optmenu = gtk_option_menu_new();
1162     menu = gtk_menu_new();
1163     
1164     g_snprintf(tmp, 100, "PPID (%u)", 0);
1165     menuitem = gtk_menu_item_new_with_label(tmp);
1166     OBJECT_SET_DATA(menuitem, "user_data", GINT_TO_POINTER(E_DECODE_PPID));
1167     gtk_menu_append(GTK_MENU(menu), menuitem);
1168     gtk_widget_show(menuitem);  /* gtk_widget_show_all() doesn't show this */
1169     
1170     for(number_of_ppid = 0; number_of_ppid < MAX_NUMBER_OF_PPIDS; number_of_ppid++)
1171       if (cfile.edt->pi.ppid[number_of_ppid] != 0) {
1172         g_snprintf(tmp, 100, "PPID (%u)", cfile.edt->pi.ppid[number_of_ppid]);
1173         menuitem = gtk_menu_item_new_with_label(tmp);
1174         OBJECT_SET_DATA(menuitem, "user_data", GINT_TO_POINTER(E_DECODE_PPID + 1 + number_of_ppid));
1175         gtk_menu_append(GTK_MENU(menu), menuitem);
1176         gtk_widget_show(menuitem);      /* gtk_widget_show_all() doesn't show this */
1177       } else
1178         break;
1179
1180     OBJECT_SET_DATA(page, E_MENU_SRCDST, menu);
1181     gtk_option_menu_set_menu(GTK_OPTION_MENU(optmenu), menu);
1182
1183     return(optmenu);
1184 }
1185
1186 /*************************************************/
1187 /*        Dialog setup - list based menus        */
1188 /*************************************************/
1189
1190 #if GTK_MAJOR_VERSION >= 2
1191 struct handle_lookup_info {
1192     dissector_handle_t handle;
1193     gboolean           found;
1194 };
1195
1196 static gboolean
1197 lookup_handle(GtkTreeModel *model, GtkTreePath *path _U_, GtkTreeIter *iter,
1198               gpointer data)
1199 {
1200     dissector_handle_t handle;
1201     struct handle_lookup_info *hli = (struct handle_lookup_info *)data;
1202
1203     gtk_tree_model_get(model, iter, E_LIST_S_TABLE+1, &handle, -1);
1204     if (hli->handle == handle) {
1205         hli->found = TRUE;
1206         return TRUE;
1207     }
1208     return FALSE;
1209 }
1210 #endif
1211
1212 /*
1213  * This routine creates one entry in the list of protocol dissector
1214  * that can be used.  It is called by the dissector_table_foreach_handle
1215  * routine once for each entry in a dissector table's list of handles
1216  * for dissectors that could be used in that table.  It guarantees unique
1217  * entries by iterating over the list of entries build up to this point,
1218  * looking for a duplicate name.  If there is no duplicate, then this
1219  * entry is added to the list of possible dissectors.
1220  *
1221  * @param table_name The name of the dissector table currently
1222  * being walked.
1223  *
1224  * @param value The dissector handle for this entry.  This is an opaque
1225  * pointer that can only be handed back to routines in the file packet.c
1226  *
1227  * @param user_data A data block passed into each instance of this
1228  * routine.  It contains information from the caller of the foreach
1229  * routine, specifying information about the dissector table and where
1230  * to store any information generated by this routine.
1231  */
1232 void
1233 decode_add_to_list (const gchar *table_name, const gchar *proto_name, gpointer value, gpointer user_data)
1234 {
1235     const gchar     *text[E_LIST_S_COLUMNS];
1236 #if GTK_MAJOR_VERSION < 2
1237     GtkCList  *list;
1238     gint       row;
1239 #else
1240     GtkTreeView  *list;
1241     GtkListStore *store;
1242     GtkTreeIter   iter;
1243     struct handle_lookup_info hli;
1244 #endif
1245
1246     g_assert(user_data);
1247     g_assert(value);
1248
1249     list = user_data;
1250
1251 #if GTK_MAJOR_VERSION < 2
1252     row = gtk_clist_find_row_from_data(list, value);
1253     /* We already have an entry for this handle.
1254      * XXX - will this ever happen? */
1255     if (row != -1) return;
1256 #else
1257     hli.handle = value;
1258     hli.found = FALSE;
1259     store = GTK_LIST_STORE(gtk_tree_view_get_model(list));
1260     gtk_tree_model_foreach(GTK_TREE_MODEL(store), lookup_handle, &hli);
1261     /* We already have an entry for this handle.
1262      * XXX - will this ever happen? */
1263     if (hli.found) return;
1264 #endif
1265
1266     text[E_LIST_S_PROTO_NAME] = proto_name;
1267     text[E_LIST_S_TABLE] = table_name;
1268 #if GTK_MAJOR_VERSION < 2
1269     row = gtk_clist_prepend(list, (gchar **) text);
1270     gtk_clist_set_row_data(list, row, value);
1271 #else
1272     gtk_list_store_append(store, &iter);
1273     gtk_list_store_set(store, &iter,
1274                        E_LIST_S_PROTO_NAME, text[E_LIST_S_PROTO_NAME],
1275                        E_LIST_S_TABLE, text[E_LIST_S_TABLE],
1276                        E_LIST_S_TABLE+1, value, -1);
1277 #endif
1278 }
1279
1280 static void
1281 decode_proto_add_to_list (const gchar *table_name, gpointer value, gpointer user_data)
1282 {
1283     const gchar     *proto_name;
1284     gint       i;
1285     dissector_handle_t handle;
1286
1287
1288     handle = value;
1289     proto_name = dissector_handle_get_short_name(handle);
1290
1291     i = dissector_handle_get_protocol_index(handle);
1292     if (i >= 0 && !proto_is_protocol_enabled(find_protocol_by_id(i)))
1293         return;
1294   
1295     decode_add_to_list (table_name, proto_name, value, user_data);
1296 }
1297
1298
1299 /*
1300  * This routine starts the creation of a List on a notebook page.  It
1301  * creates both a scrolled window and a list, adds the list to the
1302  * window, and attaches the list as a data object on the page.
1303  *
1304  * @param page A pointer to the notebook page being created.
1305  *
1306  * @param list_p Will be filled in with the address of a newly
1307  * created List.
1308  *
1309  * @param scrolled_win_p Will be filled in with the address of a newly
1310  * created GtkScrolledWindow.
1311  */
1312 void
1313 decode_list_menu_start(GtkWidget *page, GtkWidget **list_p,
1314                        GtkWidget **scrolled_win_p)
1315 {
1316 #if GTK_MAJOR_VERSION < 2
1317     gchar             *titles[E_LIST_S_COLUMNS] = {"Short Name", "Table Name"};
1318     GtkCList          *list;
1319     gint               column;
1320 #else
1321     GtkTreeView       *list;
1322     GtkListStore      *store;
1323     GtkCellRenderer   *renderer;
1324     GtkTreeViewColumn *tc;
1325     GtkTreeSortable   *sortable;
1326 #endif
1327
1328 #if GTK_MAJOR_VERSION < 2
1329     list = GTK_CLIST(gtk_clist_new_with_titles(E_LIST_S_COLUMNS, titles));
1330
1331     OBJECT_SET_DATA(decode_w, "sctp_list", list);
1332     gtk_clist_column_titles_passive(list);
1333 #ifndef DEBUG
1334     gtk_clist_column_titles_hide(list);
1335     for (column = 1; column < E_LIST_S_COLUMNS; column++)
1336         gtk_clist_set_column_visibility (list, column, FALSE);
1337 #endif
1338     for (column = 0; column < E_LIST_S_COLUMNS; column++)
1339         gtk_clist_set_column_auto_resize(list, column, TRUE);
1340     OBJECT_SET_DATA(page, E_PAGE_LIST, list);
1341 #else
1342     store = gtk_list_store_new(E_LIST_S_COLUMNS+1, G_TYPE_STRING,
1343                                G_TYPE_STRING, G_TYPE_POINTER);
1344     OBJECT_SET_DATA(G_OBJECT(decode_w), "sctp_data", store);
1345     list = GTK_TREE_VIEW(tree_view_new(GTK_TREE_MODEL(store)));
1346     sortable = GTK_TREE_SORTABLE(store);
1347     gtk_tree_sortable_set_sort_func(sortable, SORT_ALPHABETICAL, sort_iter_compare_func, GINT_TO_POINTER(SORT_ALPHABETICAL), NULL);
1348     gtk_tree_sortable_set_sort_column_id(sortable, SORT_ALPHABETICAL, GTK_SORT_ASCENDING);
1349     gtk_tree_view_set_headers_clickable(list, FALSE);
1350 #ifndef DEBUG
1351     gtk_tree_view_set_headers_visible(list, FALSE);
1352 #endif
1353     renderer = gtk_cell_renderer_text_new();
1354     tc = gtk_tree_view_column_new_with_attributes("Short Name", renderer,
1355                                                   "text", E_LIST_S_PROTO_NAME,
1356                                                   NULL);
1357     gtk_tree_view_column_set_sizing(tc, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
1358     gtk_tree_view_append_column(list, tc);
1359     g_object_set_data(G_OBJECT(page), E_PAGE_LIST, list);
1360 #endif
1361
1362     *scrolled_win_p = scrolled_window_new(NULL, NULL);
1363     /* this will result to set the width of the dialog to the required size */
1364     gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(*scrolled_win_p),
1365                                    GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
1366 #if GTK_MAJOR_VERSION >= 2
1367     gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(*scrolled_win_p), 
1368                                    GTK_SHADOW_IN);
1369 #endif
1370 #if GTK_MAJOR_VERSION < 2
1371     gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(*scrolled_win_p),
1372                                           GTK_WIDGET(list));
1373 #else
1374     gtk_container_add(GTK_CONTAINER(*scrolled_win_p), GTK_WIDGET(list));
1375 #endif
1376
1377     *list_p = GTK_WIDGET(list);
1378 }
1379
1380 /*
1381  * This routine finishes the creation of a List on a notebook page.
1382  * It adds the default entry, sets the default entry as the
1383  * highlighted entry, and sorts the List.
1384  *
1385  * @param list A pointer the the List to finish.
1386  */
1387 void
1388 decode_list_menu_finish(GtkWidget *list)
1389 {
1390     const gchar *text[E_LIST_S_COLUMNS];
1391 #if GTK_MAJOR_VERSION < 2
1392     gint row;
1393 #else
1394     GtkListStore *store;
1395     GtkTreeIter   iter;
1396 #endif
1397
1398     text[E_LIST_S_PROTO_NAME] = "(default)";
1399     text[E_LIST_S_TABLE] = "(none)";
1400 #if GTK_MAJOR_VERSION < 2
1401     row = gtk_clist_prepend(GTK_CLIST(list), (gchar **) text);
1402     gtk_clist_set_row_data(GTK_CLIST(list), row, NULL);
1403
1404     gtk_clist_select_row(GTK_CLIST(list), 0, -1);
1405     gtk_clist_sort(GTK_CLIST(list));
1406 #else
1407     store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(list)));
1408     gtk_list_store_prepend(store, &iter);
1409     gtk_list_store_set(store, &iter,
1410                        E_LIST_S_PROTO_NAME, text[E_LIST_S_PROTO_NAME],
1411                        E_LIST_S_TABLE, text[E_LIST_S_TABLE],
1412                        E_LIST_S_TABLE+1, NULL, -1);
1413
1414     gtk_tree_selection_select_iter(gtk_tree_view_get_selection(GTK_TREE_VIEW(list)), &iter);
1415 #endif
1416 }
1417
1418 /*
1419  * This routine is called to add the dissector selection list to a
1420  * notebook page.  This scrolled list contains an entry labeled
1421  * "default", and an entry for each protocol that has had a dissector
1422  * registered.  The default choice for the list is set to the
1423  * "default" choice, which will return the protocol/port selections to
1424  * their original dissector(s).
1425  *
1426  * @param page A pointer to the notebook page currently being created.
1427  *
1428  * @param table_name The name of the dissector table to use to build
1429  * this (list) menu.
1430  *
1431  * @return GtkWidget * A pointer to the newly created list within a
1432  * scrolled window.
1433  */
1434 static GtkWidget *
1435 decode_add_simple_menu (GtkWidget *page, const gchar *table_name)
1436 {
1437     GtkWidget *scrolled_window;
1438     GtkWidget *list;
1439
1440     decode_list_menu_start(page, &list, &scrolled_window);
1441     dissector_table_foreach_handle(table_name, decode_proto_add_to_list, list);
1442     decode_list_menu_finish(list);
1443     return(scrolled_window);
1444 }
1445
1446
1447 /**************************************************/
1448 /*                  Dialog setup                  */
1449 /**************************************************/
1450
1451 /*
1452  * This routine creates a sample notebook page in the dialog box.
1453  * This notebook page provides a prompt specifying what is being
1454  * changed and its current value (e.g. "IP Protocol number (17)"), and
1455  * a list specifying all the available choices.  The list of choices
1456  * is conditionally enabled, based upon the setting of the
1457  * "decode"/"do not decode" radio buttons.
1458  *
1459  * @param prompt The prompt for this notebook page
1460  *
1461  * @param title A title for this page to use when debugging.
1462  *
1463  * @param table_name The name of the dissector table to use to
1464  * build this page.
1465  *
1466  * @param value The protocol/port value that is to be changed.
1467  *
1468  * @return GtkWidget * A pointer to the notebook page created by this
1469  * routine.
1470  */
1471 static GtkWidget *
1472 decode_add_simple_page (const gchar *prompt, const gchar *title, const gchar *table_name,
1473                         guint value)
1474 {
1475     GtkWidget   *page, *label, *scrolled_window;
1476
1477     page = gtk_hbox_new(FALSE, 5);
1478     OBJECT_SET_DATA(page, E_PAGE_ACTION, decode_simple);
1479     OBJECT_SET_DATA(page, E_PAGE_TABLE, (gchar *) table_name);
1480     OBJECT_SET_DATA(page, E_PAGE_TITLE, (gchar *) title);
1481     OBJECT_SET_DATA(page, E_PAGE_VALUE, GUINT_TO_POINTER(value));
1482
1483     /* Always enabled */
1484     label = gtk_label_new(prompt);
1485     gtk_box_pack_start(GTK_BOX(page), label, TRUE, TRUE, 0);
1486
1487     /* Conditionally enabled - only when decoding packets */
1488     label = gtk_label_new("as");
1489     gtk_box_pack_start(GTK_BOX(page), label, TRUE, TRUE, 0);
1490     decode_dimmable = g_slist_prepend(decode_dimmable, label);
1491     scrolled_window = decode_add_simple_menu(page, table_name);
1492     gtk_box_pack_start(GTK_BOX(page), scrolled_window, TRUE, TRUE, 0);
1493     decode_dimmable = g_slist_prepend(decode_dimmable, scrolled_window);
1494
1495     return(page);
1496 }
1497
1498
1499 /*
1500  * This routine creates the TCP or UDP notebook page in the dialog box.
1501  * All items created by this routine are packed into a single
1502  * horizontal box.  First is a label indicating whether the port(s) for
1503  * which the user can set the dissection is a TCP port or a UDP port.
1504  * Second is a menu allowing the user to select whether the source port,
1505  * destination port, or both ports will have dissectors added for them.
1506  * Last is a (conditionally enabled) popup menu listing all possible
1507  * dissectors that can be used to decode the packets, and the choice
1508  * or returning to the default dissector for these ports.
1509  *
1510  * The defaults for these items are the transport layer protocol of
1511  * the currently selected packet, the source port of the currently
1512  * selected packet, and the "default dissector".
1513  *
1514  * @param prompt The prompt for this notebook page
1515  *
1516  * @param table_name The name of the dissector table to use to
1517  * build this page.
1518  *
1519  * @return GtkWidget * A pointer to the notebook page created by
1520  * this routine.
1521  */
1522 static GtkWidget *
1523 decode_add_tcpudp_page (const gchar *prompt, const gchar *table_name)
1524 {
1525     GtkWidget   *page, *label, *scrolled_window, *optmenu;
1526
1527     page = gtk_hbox_new(FALSE, 5);
1528     OBJECT_SET_DATA(page, E_PAGE_ACTION, decode_transport);
1529     OBJECT_SET_DATA(page, E_PAGE_TABLE, (gchar *) table_name);
1530     OBJECT_SET_DATA(page, E_PAGE_TITLE, "Transport");
1531
1532     /* Always enabled */
1533     label = gtk_label_new(prompt);
1534     gtk_box_pack_start(GTK_BOX(page), label, TRUE, TRUE, 0);
1535     optmenu = decode_add_srcdst_menu(page);
1536     gtk_box_pack_start(GTK_BOX(page), optmenu, TRUE, TRUE, 0);
1537     label = gtk_label_new("port(s)");
1538     gtk_box_pack_start(GTK_BOX(page), label, TRUE, TRUE, 0);
1539
1540     /* Conditionally enabled - only when decoding packets */
1541     label = gtk_label_new("as");
1542     gtk_box_pack_start(GTK_BOX(page), label, TRUE, TRUE, 0);
1543     decode_dimmable = g_slist_prepend(decode_dimmable, label);
1544     scrolled_window = decode_add_simple_menu(page, table_name);
1545     gtk_box_pack_start(GTK_BOX(page), scrolled_window, TRUE, TRUE, 0);
1546     decode_dimmable = g_slist_prepend(decode_dimmable, scrolled_window);
1547
1548     return(page);
1549 }
1550
1551 static void
1552 decode_sctp_list_menu_start(GtkWidget **list_p, GtkWidget **scrolled_win_p)
1553 {
1554 #if GTK_MAJOR_VERSION < 2
1555 /*    gchar             *titles[E_LIST_S_COLUMNS] = {"Short Name", "Table Name"};*/
1556     GtkCList          *list;
1557     gint               column;
1558 #else
1559     GtkTreeView       *list;
1560     GtkListStore      *sctp_store;
1561     GtkCellRenderer   *renderer;
1562     GtkTreeViewColumn *tc;
1563     GtkTreeSortable   *sortable;
1564 #endif
1565
1566 #if GTK_MAJOR_VERSION < 2
1567     list=OBJECT_GET_DATA(decode_w, "sctp_list");
1568     gtk_clist_column_titles_passive(list);
1569 #ifndef DEBUG
1570     gtk_clist_column_titles_hide(list);
1571     for (column = 1; column < E_LIST_S_COLUMNS; column++)
1572         gtk_clist_set_column_visibility (list, column, FALSE);
1573 #endif
1574     for (column = 0; column < E_LIST_S_COLUMNS; column++)
1575         gtk_clist_set_column_auto_resize(list, column, TRUE);
1576 #else
1577     sctp_store = OBJECT_GET_DATA(decode_w, "sctp_data");
1578     list = GTK_TREE_VIEW(tree_view_new(GTK_TREE_MODEL(sctp_store)));
1579     sortable = GTK_TREE_SORTABLE(sctp_store);
1580     gtk_tree_sortable_set_sort_func(sortable, SORT_ALPHABETICAL, sort_iter_compare_func, GINT_TO_POINTER(SORT_ALPHABETICAL), NULL);
1581     gtk_tree_sortable_set_sort_column_id(sortable, SORT_ALPHABETICAL, GTK_SORT_ASCENDING);
1582     gtk_tree_view_set_headers_clickable(list, FALSE);
1583 #ifndef DEBUG
1584     gtk_tree_view_set_headers_visible(list, FALSE);
1585 #endif
1586     renderer = gtk_cell_renderer_text_new();
1587     tc = gtk_tree_view_column_new_with_attributes("Short Name", renderer,
1588                                                   "text", E_LIST_S_PROTO_NAME,
1589                                                   NULL);
1590     gtk_tree_view_column_set_sizing(tc, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
1591     gtk_tree_view_append_column(list, tc);
1592 #endif
1593
1594     *scrolled_win_p = scrolled_window_new(NULL, NULL);
1595     /* this will result to set the width of the dialog to the required size */
1596     gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(*scrolled_win_p), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
1597 #if GTK_MAJOR_VERSION >= 2
1598     gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(*scrolled_win_p), GTK_SHADOW_IN);
1599     gtk_container_add(GTK_CONTAINER(*scrolled_win_p), GTK_WIDGET(list));
1600 #endif
1601     *list_p = GTK_WIDGET(list);
1602 }
1603
1604 static void
1605 decode_sctp_update_ppid_menu(GtkWidget *w _U_, GtkWidget *page)
1606 {
1607     GtkWidget *menu, *menuitem, *list, *scrolled_window, *sctpmenu;
1608     gchar      tmp[100];
1609     guint      number_of_ppid;
1610 #if GTK_MAJOR_VERSION < 2
1611     GtkCList *sctp_list;
1612 #else
1613     GtkListStore *sctp_store;
1614 #endif
1615
1616     menu = gtk_menu_new();
1617
1618     g_snprintf(tmp, 100, "PPID (%u)", 0);
1619     menuitem = gtk_menu_item_new_with_label(tmp);
1620     OBJECT_SET_DATA(menuitem, "user_data", GINT_TO_POINTER(E_DECODE_PPID));
1621     gtk_menu_append(GTK_MENU(menu), menuitem);
1622     gtk_widget_show(menuitem);  /* gtk_widget_show_all() doesn't show this */
1623     for(number_of_ppid = 0; number_of_ppid < MAX_NUMBER_OF_PPIDS; number_of_ppid++)
1624       if (cfile.edt->pi.ppid[number_of_ppid] != 0) {
1625         g_snprintf(tmp, 100, "PPID (%u)", cfile.edt->pi.ppid[number_of_ppid]);
1626         menuitem = gtk_menu_item_new_with_label(tmp);
1627         OBJECT_SET_DATA(menuitem, "user_data", GINT_TO_POINTER(E_DECODE_PPID + 1 + number_of_ppid));
1628         gtk_menu_append(GTK_MENU(menu), menuitem);
1629         gtk_widget_show(menuitem);      /* gtk_widget_show_all() doesn't show this */
1630       } else
1631         break;
1632
1633     OBJECT_SET_DATA(page, E_MENU_SRCDST, menu);
1634     OBJECT_SET_DATA(page, E_PAGE_TABLE, "sctp.ppi");
1635     sctpmenu = OBJECT_GET_DATA(decode_w, "user_data");
1636     gtk_option_menu_set_menu(GTK_OPTION_MENU(sctpmenu), menu);
1637
1638 #if GTK_MAJOR_VERSION < 2
1639     sctp_list = OBJECT_GET_DATA(decode_w, "sctp_list");
1640     gtk_clist_clear(sctp_list);
1641 #else
1642     sctp_store = OBJECT_GET_DATA(G_OBJECT(decode_w), "sctp_data");
1643     gtk_list_store_clear(sctp_store);
1644 #endif
1645     decode_sctp_list_menu_start(&list, &scrolled_window);
1646     dissector_table_foreach_handle("sctp.ppi", decode_proto_add_to_list, list);
1647     decode_list_menu_finish(list);
1648 }
1649
1650
1651 static void
1652 decode_sctp_update_srcdst_menu(GtkWidget *w _U_, GtkWidget *page)
1653 {
1654     GtkWidget  *menu, *menuitem, *scrolled_window, *list, *sctpmenu;
1655     gchar      tmp[100];
1656 #if GTK_MAJOR_VERSION < 2
1657     GtkCList    *sctp_list;
1658 #else
1659     GtkListStore *sctp_store;
1660 #endif
1661
1662     menu = gtk_menu_new();
1663     g_snprintf(tmp, 100, "source (%u)", cfile.edt->pi.srcport);
1664     menuitem = gtk_menu_item_new_with_label(tmp);
1665     OBJECT_SET_DATA(menuitem, "user_data", GINT_TO_POINTER(E_DECODE_SPORT));
1666     gtk_menu_append(GTK_MENU(menu), menuitem);
1667     gtk_widget_show(menuitem);  /* gtk_widget_show_all() doesn't show this */
1668
1669     g_snprintf(tmp, 100, "destination (%u)", cfile.edt->pi.destport);
1670     menuitem = gtk_menu_item_new_with_label(tmp);
1671     OBJECT_SET_DATA(menuitem, "user_data", GINT_TO_POINTER(E_DECODE_DPORT));
1672     gtk_menu_append(GTK_MENU(menu), menuitem);
1673     gtk_widget_show(menuitem);  /* gtk_widget_show_all() doesn't show this */
1674
1675     menuitem = gtk_menu_item_new_with_label("both");
1676     OBJECT_SET_DATA(menuitem, "user_data", GINT_TO_POINTER(E_DECODE_BPORT));
1677     gtk_menu_append(GTK_MENU(menu), menuitem);
1678     gtk_widget_show(menuitem);  /* gtk_widget_show_all() doesn't show this */
1679
1680     OBJECT_SET_DATA(page, E_MENU_SRCDST, menu);
1681     OBJECT_SET_DATA(page, E_PAGE_TABLE, "sctp.port");
1682     sctpmenu = OBJECT_GET_DATA(decode_w, "user_data");
1683     gtk_option_menu_set_menu(GTK_OPTION_MENU(sctpmenu), menu);
1684     OBJECT_SET_DATA(page, E_PAGE_SPORT, GINT_TO_POINTER(cfile.edt->pi.srcport));
1685     OBJECT_SET_DATA(page, E_PAGE_DPORT, GINT_TO_POINTER(cfile.edt->pi.destport));  
1686 #if GTK_MAJOR_VERSION < 2
1687     sctp_list = OBJECT_GET_DATA(decode_w, "sctp_list");
1688     gtk_clist_clear(sctp_list);
1689 #else
1690     sctp_store = OBJECT_GET_DATA(G_OBJECT(decode_w), "sctp_data");
1691     gtk_list_store_clear(sctp_store);
1692 #endif
1693     decode_sctp_list_menu_start(&list, &scrolled_window);
1694     dissector_table_foreach_handle("sctp.port", decode_proto_add_to_list, list);
1695     decode_list_menu_finish(list);
1696 }
1697
1698
1699
1700 static GtkWidget *
1701 decode_sctp_add_port_ppid (GtkWidget *page)
1702 {
1703     GtkWidget *format_vb, *radio_button;
1704     GSList *format_grp;
1705
1706     format_vb = gtk_vbox_new(FALSE, 2);
1707
1708     radio_button = gtk_radio_button_new_with_label(NULL, "PPID");
1709     format_grp = gtk_radio_button_group(GTK_RADIO_BUTTON(radio_button));
1710     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio_button), TRUE);
1711     SIGNAL_CONNECT(radio_button, "clicked", decode_sctp_update_ppid_menu, page);
1712
1713     gtk_box_pack_start(GTK_BOX(format_vb), radio_button, TRUE, TRUE, 0);
1714
1715     radio_button = gtk_radio_button_new_with_label(format_grp, "Port");
1716     format_grp = gtk_radio_button_group(GTK_RADIO_BUTTON(radio_button));
1717     SIGNAL_CONNECT(radio_button, "clicked", decode_sctp_update_srcdst_menu, page);
1718
1719     gtk_box_pack_start(GTK_BOX(format_vb), radio_button, TRUE, TRUE, 0);
1720
1721     return(format_vb);
1722 }
1723
1724
1725 static GtkWidget *
1726 decode_add_sctp_page (const gchar *prompt, const gchar *table_name)
1727 {
1728     GtkWidget   *page, *label, *scrolled_window,  *radio, *vbox, *alignment, *sctpbox, *sctpmenu;
1729
1730     page = gtk_hbox_new(FALSE, 5);
1731     OBJECT_SET_DATA(page, E_PAGE_ACTION, decode_transport);
1732     OBJECT_SET_DATA(page, E_PAGE_TABLE, (gchar *) table_name);
1733     OBJECT_SET_DATA(page, E_PAGE_TITLE, "Transport");
1734
1735     vbox = gtk_vbox_new(FALSE, 5);
1736     radio = decode_sctp_add_port_ppid(page);
1737     gtk_box_pack_start(GTK_BOX(vbox), radio, TRUE, TRUE, 0);
1738
1739     /* Always enabled */
1740     sctpbox = gtk_hbox_new(FALSE, 5);
1741     label = gtk_label_new(prompt);
1742     gtk_box_pack_start(GTK_BOX(sctpbox), label, TRUE, TRUE, 0);  
1743     sctpmenu = decode_add_ppid_menu(page);
1744     OBJECT_SET_DATA(decode_w, "user_data", sctpmenu);
1745     alignment = decode_add_pack_menu(sctpmenu);
1746
1747     gtk_box_pack_start(GTK_BOX(sctpbox), alignment, TRUE, TRUE, 0);
1748
1749     /* Conditionally enabled - only when decoding packets */
1750     label = gtk_label_new("as");
1751     gtk_box_pack_start(GTK_BOX(sctpbox), label, TRUE, TRUE, 0);
1752     decode_dimmable = g_slist_prepend(decode_dimmable, label);
1753     gtk_box_pack_start(GTK_BOX(vbox), sctpbox, TRUE, TRUE, 0);
1754     gtk_box_pack_start(GTK_BOX(page), vbox, TRUE, TRUE, 0);
1755
1756     scrolled_window = decode_add_simple_menu(page, table_name);
1757     gtk_box_pack_start(GTK_BOX(page), scrolled_window, TRUE, TRUE, 0);
1758     decode_dimmable = g_slist_prepend(decode_dimmable, scrolled_window);
1759
1760     return(page);
1761 }
1762
1763
1764 /*
1765  * This routine indicates whether we'd actually have any pages in the
1766  * notebook in a "Decode As" dialog box; if there wouldn't be, we
1767  * inactivate the menu item for "Decode As".
1768  */
1769 gboolean
1770 decode_as_ok(void)
1771 {
1772     return cfile.edt->pi.ethertype || cfile.edt->pi.ipproto ||
1773         cfile.edt->pi.ptype == PT_TCP || cfile.edt->pi.ptype == PT_UDP;
1774 }
1775
1776
1777 /*
1778  * This routine creates the bulk of the "Decode As" dialog box.  All
1779  * items created by this routine are packed as pages into a notebook.
1780  * There will be a page for each protocol layer that can be change.
1781  *
1782  * @param GtkWidget * A pointer to the widget in which the notebook
1783  * should be installed.
1784  */
1785 static void
1786 decode_add_notebook (GtkWidget *format_hb)
1787 {
1788     GtkWidget *notebook, *page, *label;
1789     gchar buffer[40];
1790
1791     /* Start a nootbook for flipping between sets of changes */
1792     notebook = gtk_notebook_new();
1793     gtk_container_add(GTK_CONTAINER(format_hb), notebook);
1794     OBJECT_SET_DATA(decode_w, E_NOTEBOOK, notebook);
1795
1796     /* Add link level selection page */
1797     if (cfile.edt->pi.ethertype) {
1798         g_snprintf(buffer, 40, "Ethertype 0x%04x", cfile.edt->pi.ethertype);
1799         page = decode_add_simple_page(buffer, "Link", "ethertype", cfile.edt->pi.ethertype);
1800         label = gtk_label_new("Link");
1801         gtk_notebook_append_page(GTK_NOTEBOOK(notebook), page, label);
1802     }
1803
1804     /* Add network selection page */
1805     if (cfile.edt->pi.ipproto) {
1806         /*
1807          * The network-layer protocol is IP.
1808          */
1809         g_snprintf(buffer, 40, "IP protocol %u", cfile.edt->pi.ipproto);
1810         page = decode_add_simple_page(buffer, "Network", "ip.proto", cfile.edt->pi.ipproto);
1811         OBJECT_SET_DATA(page, E_PAGE_ACTION, decode_simple);
1812         label = gtk_label_new("Network");
1813         gtk_notebook_append_page(GTK_NOTEBOOK(notebook), page, label);
1814     }
1815
1816     /* Add transport selection page */
1817     switch (cfile.edt->pi.ptype) {
1818
1819     case PT_TCP:
1820         page = decode_add_tcpudp_page("TCP", "tcp.port");
1821         break;
1822
1823     case PT_UDP:
1824         page = decode_add_tcpudp_page("UDP", "udp.port");
1825         break;
1826
1827     case PT_SCTP:
1828         page = decode_add_sctp_page("SCTP", "sctp.ppi");
1829         break;
1830
1831     default:
1832         page = NULL;
1833         break;
1834     }
1835     if (page != NULL) {
1836         label = gtk_label_new("Transport");
1837         gtk_notebook_append_page(GTK_NOTEBOOK(notebook), page, label);
1838     }
1839
1840     if(cfile.edt->pi.dcetransporttype != -1) {
1841             page = decode_dcerpc_add_page(&cfile.edt->pi);
1842             label = gtk_label_new("DCE-RPC");
1843             gtk_notebook_append_page(GTK_NOTEBOOK(notebook), page, label);
1844         OBJECT_SET_DATA(decode_w, E_PAGE_DCERPC, page);
1845     }
1846
1847     /* Select the last added page (selects first by default) */
1848     /* Notebook must be visible for set_page to work. */
1849     gtk_widget_show_all(notebook);
1850     gtk_notebook_set_page(GTK_NOTEBOOK(notebook), -1);
1851
1852 }
1853
1854
1855 /*
1856  * This routine creates the "Decode As" dialog box. This dialog box
1857  * asks the user which protocol to use for decoding the currently
1858  * selected packet.  This will affect the last packet that we called a
1859  * dissection routine on belongs (this might be the most recently
1860  * selected packet, or it might be the last packet in the file).
1861  *
1862  * This routine uses an auxiliary function to create the bulk of the
1863  * dialog box, and then hand crafts the button box at the bottom of
1864  * the dialog.
1865  *
1866  * @param w Unknown
1867  * @param data Unknown
1868  */
1869 void
1870 decode_as_cb (GtkWidget * w _U_, gpointer data _U_)
1871 {
1872     GtkWidget   *main_vb, *format_hb, *bbox, *ok_bt, *close_bt, *help_bt, *button;
1873     GtkWidget   *button_vb, *apply_bt;
1874     GtkTooltips *tooltips = gtk_tooltips_new();
1875
1876     if (decode_w != NULL) {
1877         /* There's already a "Decode As" dialog box; reactivate it. */
1878         reactivate_window(decode_w);
1879         return;
1880     }
1881
1882     requested_action = E_DECODE_YES;
1883     decode_w = dlg_window_new("Wireshark: Decode As");
1884         /* Provide a minimum of a couple of rows worth of data */
1885     gtk_window_set_default_size(GTK_WINDOW(decode_w), -1, E_DECODE_MIN_HEIGHT);
1886
1887     /* Container for each row of widgets */
1888     main_vb = gtk_vbox_new(FALSE, 2);
1889     gtk_container_border_width(GTK_CONTAINER(main_vb), 5);
1890     gtk_container_add(GTK_CONTAINER(decode_w), main_vb);
1891
1892     /* First row - Buttons and Notebook */
1893     {
1894         format_hb = gtk_hbox_new(FALSE, 5);
1895         gtk_box_pack_start(GTK_BOX(main_vb), format_hb, TRUE, TRUE, 10);
1896
1897         button_vb = decode_add_yes_no();
1898         gtk_box_pack_start(GTK_BOX(format_hb), button_vb, TRUE, TRUE, 10);
1899
1900     button = gtk_button_new_with_label("Show Current");
1901     SIGNAL_CONNECT(button, "clicked", decode_show_cb, decode_w);
1902     GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
1903     gtk_box_pack_start(GTK_BOX(button_vb), button, FALSE, FALSE, 0);
1904     gtk_tooltips_set_tip(tooltips, button, 
1905         "Open a dialog showing the current settings.", NULL);
1906
1907     button = gtk_button_new_with_label("Clear");
1908     SIGNAL_CONNECT(button, "clicked", decode_clear_cb, decode_w);
1909     GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
1910     gtk_box_pack_start(GTK_BOX(button_vb), button, FALSE, FALSE, 0);
1911     gtk_tooltips_set_tip(tooltips, button, 
1912         "Clear ALL settings.", NULL);
1913
1914         decode_add_notebook(format_hb);
1915     }
1916
1917     /* Button row */
1918     if(topic_available(HELP_DECODE_AS_DIALOG)) {
1919         bbox = dlg_button_row_new(GTK_STOCK_OK, GTK_STOCK_APPLY, GTK_STOCK_CLOSE, GTK_STOCK_HELP, NULL);
1920     } else {
1921         bbox = dlg_button_row_new(GTK_STOCK_OK, GTK_STOCK_APPLY, GTK_STOCK_CLOSE, NULL);
1922     }
1923     gtk_box_pack_start(GTK_BOX(main_vb), bbox, FALSE, FALSE, 0);
1924     gtk_widget_show(bbox);
1925
1926     ok_bt = OBJECT_GET_DATA(bbox, GTK_STOCK_OK);
1927     SIGNAL_CONNECT(ok_bt, "clicked", decode_ok_cb, decode_w);
1928     gtk_tooltips_set_tip(tooltips, ok_bt, 
1929         "Apply current setting, close dialog and redissect packets.", NULL);
1930
1931     apply_bt = OBJECT_GET_DATA(bbox, GTK_STOCK_APPLY);
1932     SIGNAL_CONNECT(apply_bt, "clicked", decode_apply_cb, decode_w);
1933     gtk_tooltips_set_tip(tooltips, apply_bt, 
1934         "Apply current setting, redissect packets and keep dialog open.", NULL);
1935
1936     close_bt = OBJECT_GET_DATA(bbox, GTK_STOCK_CLOSE);
1937     window_set_cancel_button(decode_w, close_bt, NULL);
1938     SIGNAL_CONNECT(close_bt, "clicked", decode_close_cb, decode_w);
1939     gtk_tooltips_set_tip(tooltips, close_bt, 
1940         "Close the dialog, don't redissect packets.", NULL);
1941
1942     if(topic_available(HELP_DECODE_AS_DIALOG)) {
1943         help_bt = OBJECT_GET_DATA(bbox, GTK_STOCK_HELP);
1944         SIGNAL_CONNECT(help_bt, "clicked", topic_cb, HELP_DECODE_AS_DIALOG);
1945     }
1946
1947     gtk_widget_grab_default(ok_bt);
1948
1949     SIGNAL_CONNECT(decode_w, "delete_event", decode_delete_cb, NULL);
1950     SIGNAL_CONNECT(decode_w, "destroy", decode_destroy_cb, NULL);
1951
1952     gtk_widget_show_all(decode_w);
1953     window_present(decode_w);
1954 }