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