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