82c7db15e4faa1372b7d96dae76aa97b6f3b4241
[metze/wireshark/wip.git] / ui / gtk / decode_as_dlg.c
1 /* decode_as_dlg.c
2  *
3  * Routines to modify dissector tables on the fly.
4  *
5  * By David Hampton <dhampton@mac.com>
6  * Copyright 2001 David Hampton
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21  */
22 #include "config.h"
23
24 #include <gtk/gtk.h>
25 #include <gdk/gdkkeysyms.h>
26 #if GTK_CHECK_VERSION(3,0,0)
27 # include <gdk/gdkkeysyms-compat.h>
28 #endif
29
30 #include <epan/packet.h>
31 #include <epan/epan_dissect.h>
32 #include <epan/decode_as.h>
33 #include <epan/prefs.h>
34 #include <epan/prefs-int.h>
35 #include <epan/dissectors/packet-dcerpc.h>
36
37 #include "ui/decode_as_utils.h"
38 #include "ui/simple_dialog.h"
39 #include <wsutil/utf8_entities.h>
40
41 #include "ui/gtk/main.h"
42 #include "ui/gtk/decode_as_dlg.h"
43 #include "ui/gtk/dlg_utils.h"
44 #include "ui/gtk/gui_utils.h"
45 #include "ui/gtk/help_dlg.h"
46 #include "ui/gtk/old-gtk-compat.h"
47 #include "ui/gtk/packet_win.h"
48 #include "ui/gtk/stock_icons.h"
49
50 #undef DEBUG
51
52 /**************************************************/
53 /*                Typedefs & Enums                */
54 /**************************************************/
55
56 #define E_DECODE_MIN_HEIGHT 300
57 #define E_NOTEBOOK "notebook"
58
59 #define E_COMBO_BOX_MULTIVALUE "combo_box_multivalue"
60
61 #define E_PAGE_DECODE_AS_DATA  "decode_as_data"
62
63 /*
64  * Columns for a "Display" list
65  */
66 #define E_LIST_D_TABLE      0
67 #define E_LIST_D_SELECTOR   1
68 #define E_LIST_D_INITIAL    2
69 #define E_LIST_D_CURRENT    3
70 #define E_LIST_D_MAX        E_LIST_D_CURRENT
71 #define E_LIST_D_COLUMNS   (E_LIST_D_MAX + 1)
72
73 /*
74  * Columns for a "Select" list.
75  * Note that most of these columns aren't displayed; they're attached
76  * to the row of the table as additional information.
77  */
78 #define E_LIST_S_PROTO_NAME 0
79 #define E_LIST_S_TABLE      1
80 /* The following is for debugging in decode_add_to_list */
81 #define E_LIST_S_MAX        E_LIST_S_TABLE
82 #define E_LIST_S_COLUMNS   (E_LIST_S_MAX + 1)
83
84 #define E_PAGE_LIST           "notebook_page_list"
85 #define E_PAGE_TABLE          "notebook_page_table_name"
86 #define E_PAGE_TITLE          "notebook_page_title"
87 #define E_PAGE_VALUE          "notebook_page_value"
88 #define E_PAGE_CURR_LAYER_NUM "notebook_page_curr_layer_num"
89
90 #define E_PAGE_ACTION "notebook_page_action"
91
92 /**************************************************/
93 /*             File Global Variables              */
94 /**************************************************/
95
96 /*
97  * Keep a static pointer to the current "Decode As" window.  This is
98  * kept so that if somebody tries to do "Tools:Decode As" while
99  * there's already a "Decode As" window up, we just pop up the
100  * existing one, rather than creating a new one.
101  */
102 static GtkWidget *decode_w = NULL;
103
104 /*
105  * A static pointer to the current "Decode As:Show" window.  This is
106  * kept so that if somebody tries to do clock the "Show Current"
107  * button or select the "Display:User Specified Decodes" menu item
108  * while there's already a "Decode As:Show" window up, we just pop up
109  * the existing one, rather than creating a new one.
110  */
111 static GtkWidget *decode_show_w = NULL;
112
113 /*
114  * A list of the dialog items that only have meaning when the user has
115  * selected the "Decode" radio button.  When the "Do not decode"
116  * button is selected these items should be dimmed.
117  */
118 GSList *decode_dimmable = NULL;
119
120 /*
121  * Remember the "action" radio button that is currently selected in
122  * the dialog.  This value is initialized when the dialog is created,
123  * modified in a callback routine, and read in the routine that
124  * handles a click in the "OK" button for the dialog.
125  */
126 enum action_type  requested_action = (enum action_type)-1;
127
128
129 /**************************************************/
130 /*            Global Functions                    */
131 /**************************************************/
132
133 /**************************************************/
134 /*             Saving "Decode As"                 */
135 /**************************************************/
136
137 /*
138  * Data structure to hold information of the "Decode As" entry.
139  */
140 struct da_entry {
141     gchar *table;
142     guint selector;
143     gchar *initial;
144     gchar *current;
145 };
146
147 /*
148  * A typedef for the "Decode As" entry.
149  */
150 typedef struct da_entry da_entry_t;
151
152 /*
153  * Container that holds the entries of the "Decode As"
154  */
155 GSList *da_entries = NULL;
156
157 /*
158  * Free memory used by the da_entry
159  */
160 static void
161 free_da_entry(gpointer item, gpointer user_data _U_)
162 {
163     da_entry_t *entry = (da_entry_t *)item;
164     g_free(entry->table);
165     g_free(entry->initial);
166     g_free(entry->current);
167 }
168
169
170 /**************************************************/
171 /*             Show Changed Dissectors            */
172 /**************************************************/
173
174 #define SORT_ALPHABETICAL 0
175
176 static gint
177 sort_iter_compare_func (GtkTreeModel *model,
178                         GtkTreeIter *a,
179                         GtkTreeIter *b,
180                         gpointer user_data)
181 {
182     gint sortcol = GPOINTER_TO_INT(user_data);
183     gint ret = 0;
184     switch (sortcol)
185     {
186         case SORT_ALPHABETICAL:
187         {
188         gchar *name1, *name2;
189         gtk_tree_model_get(model, a, 0, &name1, -1);
190         gtk_tree_model_get(model, b, 0, &name2, -1);
191         if (name1 == NULL || name2 == NULL)
192         {
193             if (name1 == NULL && name2 == NULL)
194                 break; /* both equal => ret = 0 */
195             ret = (name1 == NULL) ? -1 : 1;
196         }
197         else
198         {
199             ret = g_ascii_strcasecmp(name1,name2);
200         }
201         g_free(name1);
202         g_free(name2);
203         }
204         break;
205         default:
206         g_return_val_if_reached(0);
207     }
208     return ret;
209 }
210
211
212 static void
213 decode_add_to_show_list (gpointer list_data,
214                          const gchar *table_name,
215                          gchar *selector_name,
216                          const gchar *initial_proto_name,
217                          const gchar *current_proto_name)
218 {
219     const gchar     *text[E_LIST_D_COLUMNS];
220     GtkListStore *store;
221     GtkTreeIter   iter;
222
223     store = (GtkListStore *)list_data;
224
225     text[E_LIST_D_TABLE] = table_name;
226     text[E_LIST_D_SELECTOR] = selector_name;
227     text[E_LIST_D_INITIAL] = initial_proto_name;
228     text[E_LIST_D_CURRENT] = current_proto_name;
229     gtk_list_store_append(store, &iter);
230     gtk_list_store_set(store, &iter, E_LIST_D_TABLE, text[E_LIST_D_TABLE],
231                        E_LIST_D_SELECTOR, text[E_LIST_D_SELECTOR],
232                        E_LIST_D_INITIAL, text[E_LIST_D_INITIAL],
233                        E_LIST_D_CURRENT, text[E_LIST_D_CURRENT], -1);
234 }
235
236
237 /*
238  * This routine creates one entry in the list of protocol dissector
239  * that have been changed.  It is called by the g_hash_foreach routine
240  * once for each changed entry in a dissector table.
241  *
242  * @param table_name The table name in which this dissector is found.
243  *
244  * @param key A pointer to the key for this entry in the dissector
245  * hash table.  This is generally the numeric selector of the
246  * protocol, i.e. the ethernet type code, IP port number, TCP port
247  * number, etc.
248  *
249  * @param value A pointer to the value for this entry in the dissector
250  * hash table.  This is an opaque pointer that can only be handed back
251  * to routine in the file packet.c
252  *
253  * @param user_data A pointer to the list in which this information
254  * should be stored.
255  */
256 static void
257 decode_build_show_list (const gchar *table_name, ftenum_t selector_type,
258                         gpointer key, gpointer value, gpointer user_data)
259 {
260     dissector_handle_t current, initial;
261     const gchar *current_proto_name, *initial_proto_name;
262     gchar       *selector_name;
263     gchar        string1[20];
264     da_entry_t *entry;
265
266     entry = g_new(da_entry_t,1);
267
268     g_assert(user_data);
269     g_assert(value);
270
271     current = dtbl_entry_get_handle((dtbl_entry_t *)value);
272     if (current == NULL)
273         current_proto_name = DECODE_AS_NONE;
274     else
275         current_proto_name = dissector_handle_get_short_name(current);
276     initial = dtbl_entry_get_initial_handle((dtbl_entry_t *)value);
277     if (initial == NULL)
278         initial_proto_name = DECODE_AS_NONE;
279     else
280         initial_proto_name = dissector_handle_get_short_name(initial);
281
282     switch (selector_type) {
283
284     case FT_UINT8:
285     case FT_UINT16:
286     case FT_UINT24:
287     case FT_UINT32:
288         switch (get_dissector_table_param(table_name)) {
289
290         case BASE_DEC:
291             g_snprintf(string1, sizeof(string1), "%u", GPOINTER_TO_UINT(key));
292             break;
293
294         case BASE_HEX:
295             switch (get_dissector_table_selector_type(table_name)) {
296
297             case FT_UINT8:
298                 g_snprintf(string1, sizeof(string1), "0x%02x", GPOINTER_TO_UINT(key));
299                 break;
300
301             case FT_UINT16:
302                 g_snprintf(string1, sizeof(string1), "0x%04x", GPOINTER_TO_UINT(key));
303                 break;
304
305             case FT_UINT24:
306                 g_snprintf(string1, sizeof(string1), "0x%06x", GPOINTER_TO_UINT(key));
307                 break;
308
309             case FT_UINT32:
310                 g_snprintf(string1, sizeof(string1), "0x%08x", GPOINTER_TO_UINT(key));
311                 break;
312
313             default:
314                 g_assert_not_reached();
315                 break;
316             }
317             break;
318
319         case BASE_OCT:
320             g_snprintf(string1, sizeof(string1), "%#o", GPOINTER_TO_UINT(key));
321             break;
322         }
323         selector_name = string1;
324         break;
325
326     case FT_STRING:
327     case FT_STRINGZ:
328     case FT_UINT_STRING:
329     case FT_STRINGZPAD:
330         selector_name = (gchar *)key;
331         break;
332
333     default:
334         g_assert_not_reached();
335         selector_name = NULL;
336         break;
337     }
338
339     decode_add_to_show_list (
340         user_data,
341         get_dissector_table_ui_name(table_name),
342         selector_name,
343         initial_proto_name,
344         current_proto_name);
345
346     entry->table    = g_strdup(table_name);
347     entry->selector = GPOINTER_TO_UINT(key);
348     entry->initial  = g_strdup(initial_proto_name);
349     entry->current  = g_strdup(current_proto_name);
350     da_entries = g_slist_append(da_entries, entry);
351 }
352
353
354 /*
355  * This routine is called when the user clicks the "OK" button in
356  * the "Decode As:Show..." dialog window.  This routine destroys the
357  * dialog box and performs other housekeeping functions.
358  *
359  * @param ok_bt A pointer to the "OK" button.
360  *
361  * @param parent_w A pointer to the dialog window.
362  */
363 static void
364 decode_show_ok_cb (GtkWidget *ok_bt _U_, gpointer parent_w)
365 {
366     window_destroy(GTK_WIDGET(parent_w));
367 }
368
369
370 /*
371  * This routine is called when the user clicks the "Clear" button in
372  * the "Decode As:Show..." dialog window.  This routine resets all the
373  * dissector values and then destroys the dialog box and performs
374  * other housekeeping functions.
375  *
376  * @param clear_bt A pointer to the "Clear" button.
377  *
378  * @param parent_w A pointer to the dialog window.
379  */
380 static void
381 decode_show_clear_cb (GtkWidget *clear_bt _U_, gpointer parent_w)
382 {
383     decode_clear_all();
384     redissect_packets();
385     redissect_all_packet_windows();
386
387     window_destroy(GTK_WIDGET(parent_w));
388
389     decode_show_cb(NULL, NULL);
390 }
391
392
393 /*
394  * This routine is called when the user clicks the X at the top right end in
395  * the "Decode As:Show..." dialog window.  This routine simply calls the
396  * ok routine as if the user had clicked the ok button.
397  *
398  * @param win       A pointer to the dialog box.
399  *
400  * @param event     A pointer to the event struct
401  *
402  * @param user_data Unused
403  */
404 static gboolean
405 decode_show_delete_cb (GtkWidget *win _U_, GdkEvent *event _U_, gpointer user_data _U_)
406 {
407     decode_show_ok_cb(NULL, decode_show_w);
408     return FALSE;
409 }
410
411
412 /*
413  * This routine is called at the destruction of the "Decode As:Show"
414  * dialog box.  It clears the pointer maintained by this file, so that
415  * the next time the user clicks the "Decode As:Show" button a new
416  * dialog box will be created.
417  *
418  * @param win A pointer to the dialog box.
419  *
420  * @param user_data Unused
421  */
422 static void
423 decode_show_destroy_cb (GtkWidget *win _U_, gpointer user_data _U_)
424 {
425     /* Note that we no longer have a "Decode As:Show" dialog box. */
426     decode_show_w = NULL;
427
428     /* Clear saved "Decode As" entries. */
429     g_slist_foreach(da_entries, free_da_entry, NULL);
430     g_slist_free(da_entries);
431     da_entries = NULL;
432 }
433
434
435 /*
436  * This routine saves the current "Decode As"-entries into the
437  * preferences file
438  *
439  * @param win Unused
440  *
441  * @param user_data Unused
442  */
443 static void
444 decode_show_save_cb (GtkWidget *win _U_, gpointer user_data _U_)
445 {
446     gchar* err = NULL;
447
448     if (save_decode_as_entries(&err) < 0)
449     {
450         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", err);
451         g_free(err);
452     }
453 }
454
455 /* add a single binding to the Show list */
456 static void
457 decode_dcerpc_add_show_list_single(gpointer data, gpointer user_data)
458 {
459     gchar      string1[20];
460
461
462     decode_dcerpc_bind_values_t *binding = (decode_dcerpc_bind_values_t *)data;
463
464     g_snprintf(string1, sizeof(string1), "ctx_id: %u", binding->ctx_id);
465
466     decode_add_to_show_list (
467         user_data,
468         "DCE-RPC",
469         string1,
470         "-",
471         binding->ifname->str);
472 }
473
474 /*
475  * This routine creates the "Decode As:Show" dialog box. This dialog box
476  * shows the user which protocols have had their dissectors changed.
477  *
478  * @param w Unused
479  *
480  * @param user_data Unused
481  */
482 void
483 decode_show_cb (GtkWidget *w _U_, gpointer user_data _U_)
484 {
485     GtkWidget         *main_vb, *bbox, *ok_bt, *clear_bt, *save_bt, *help_bt, *scrolled_window;
486     const gchar       *titles[E_LIST_D_COLUMNS] = {
487         "Table", "Value", "Initial", "Current"
488     };
489     gint               column;
490     GtkListStore      *store;
491     GtkTreeView       *list;
492     GtkCellRenderer   *renderer;
493     GtkTreeViewColumn *tc;
494     GtkTreeIter        iter;
495
496     if (decode_show_w != NULL) {
497         /* There's already a "Decode As" dialog box; reactivate it. */
498         reactivate_window(decode_show_w);
499         return;
500     }
501
502     decode_show_w = dlg_window_new("Wireshark: Decode As: Show");
503     /* Provide a minimum of a couple of rows worth of data */
504     gtk_window_set_default_size(GTK_WINDOW(decode_show_w), -1, E_DECODE_MIN_HEIGHT);
505
506     /* Container for each row of widgets */
507     main_vb = ws_gtk_box_new(GTK_ORIENTATION_VERTICAL, 2, FALSE);
508     gtk_container_set_border_width(GTK_CONTAINER(main_vb), 5);
509     gtk_container_add(GTK_CONTAINER(decode_show_w), main_vb);
510
511     /* Initialize list */
512     store = gtk_list_store_new(E_LIST_D_COLUMNS, G_TYPE_STRING,
513                                G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
514     list = GTK_TREE_VIEW(tree_view_new(GTK_TREE_MODEL(store)));
515     gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(list), TRUE);
516     gtk_tree_view_set_headers_clickable(GTK_TREE_VIEW(list), FALSE);
517     gtk_tree_selection_set_mode(gtk_tree_view_get_selection(list),
518                                 GTK_SELECTION_NONE);
519
520     for (column = 0; column < E_LIST_D_COLUMNS; column++) {
521         renderer = gtk_cell_renderer_text_new();
522         tc = gtk_tree_view_column_new_with_attributes(titles[column],
523                                                       renderer, "text",
524                                                       column, NULL);
525         gtk_tree_view_column_set_sizing(tc, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
526         gtk_tree_view_column_set_resizable(tc, TRUE);
527         gtk_tree_view_append_column(list, tc);
528     }
529
530     /* Add data */
531     dissector_all_tables_foreach_changed(decode_build_show_list, store);
532     g_object_unref(G_OBJECT(store));
533     decode_dcerpc_add_show_list(decode_dcerpc_add_show_list_single, store);
534
535     /* Put list into a scrolled window */
536     scrolled_window = scrolled_window_new(NULL, NULL);
537     /* this will result to set the width of the dialog to the required size */
538     gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window),
539                                    GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
540     gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled_window),
541                                         GTK_SHADOW_IN);
542     gtk_container_add(GTK_CONTAINER(scrolled_window),
543                       GTK_WIDGET(list));
544     gtk_box_pack_start(GTK_BOX(main_vb), scrolled_window, TRUE, TRUE, 0);
545
546     /* Button row */
547     bbox = dlg_button_row_new(GTK_STOCK_OK, GTK_STOCK_CLEAR, GTK_STOCK_SAVE, GTK_STOCK_HELP, NULL);
548     gtk_box_pack_start(GTK_BOX(main_vb), bbox, FALSE, FALSE, 0);
549     gtk_widget_show(bbox);
550
551     ok_bt = (GtkWidget *)g_object_get_data(G_OBJECT(bbox), GTK_STOCK_OK);
552     g_signal_connect(ok_bt, "clicked", G_CALLBACK(decode_show_ok_cb), decode_show_w);
553
554     clear_bt = (GtkWidget *)g_object_get_data(G_OBJECT(bbox), GTK_STOCK_CLEAR);
555     g_signal_connect(clear_bt, "clicked", G_CALLBACK(decode_show_clear_cb), decode_show_w);
556
557     save_bt = (GtkWidget *)g_object_get_data(G_OBJECT(bbox), GTK_STOCK_SAVE);
558     g_signal_connect(save_bt, "clicked", G_CALLBACK(decode_show_save_cb), decode_show_w);
559
560     help_bt =(GtkWidget *) g_object_get_data(G_OBJECT(bbox), GTK_STOCK_HELP);
561     g_signal_connect(help_bt, "clicked", G_CALLBACK(topic_cb), (gpointer)HELP_DECODE_AS_SHOW_DIALOG);
562
563     /* set ok as default, this button won't change anything */
564     window_set_cancel_button(decode_show_w, ok_bt, NULL);
565
566     g_signal_connect(decode_show_w, "delete_event", G_CALLBACK(decode_show_delete_cb), NULL);
567     g_signal_connect(decode_show_w, "destroy", G_CALLBACK(decode_show_destroy_cb), NULL);
568
569     gtk_widget_set_sensitive(clear_bt,
570                              gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter));
571
572     gtk_widget_show_all(decode_show_w);
573     window_present(decode_show_w);
574 }
575
576
577 /**************************************************/
578 /*         Modify the dissector routines          */
579 /**************************************************/
580
581
582 /**************************************************/
583 /* Action routines for the "Decode As..." dialog  */
584 /*   - called when the OK button pressed          */
585 /*   - one per notebook page                      */
586 /**************************************************/
587
588
589 #ifdef DEBUG
590 /*
591  * Print debugging information about tree view selection.  Extract all
592  * information from the tree view entry that was selected and print it to
593  * a dialog window.
594  *
595  * @param tree_view The tree view to dump.
596  *
597  * @param leadin A string to print at the start of each line.
598  */
599 static void
600 decode_debug (GtkTreeView *tree_view, gchar *leadin)
601 {
602     GtkListStore       *store;
603     GtkTreeSelection   *selection;
604     GtkTreeIter         iter;
605     char               *string, *text[E_LIST_S_COLUMNS];
606     dissector_handle_t  handle;
607
608     selection = gtk_tree_view_get_selection(tree_view);
609
610     if (gtk_tree_selection_get_selected(selection, NULL, &iter)){
611         store = GTK_LIST_STORE(gtk_tree_view_get_model(tree_view));
612         gtk_tree_model_get(GTK_TREE_MODEL(store), &iter,
613                            E_LIST_S_PROTO_NAME, &text[E_LIST_S_PROTO_NAME],
614                            E_LIST_S_TABLE, &text[E_LIST_S_TABLE],
615                            E_LIST_S_TABLE+1, &handle,
616                            -1);
617         string = g_strdup_printf("%s list: <put handle here>, name %s, table %s",
618                                  leadin, text[E_LIST_S_PROTO_NAME],
619                                  text[E_LIST_S_TABLE]);
620     } else {
621         string = g_strdup_printf("%s list row (none), aka do not decode", leadin);
622     }
623     simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK, string);
624     g_free(string);
625 }
626 #endif
627
628
629 /*
630  * This routine is called when the user clicks the "OK" button in the
631  * "Decode As..." dialog window and a 'simple' page is foremost.
632  * This routine takes care of making any changes requested to the
633  * dissector tables.  This routine is currently used for IP and
634  * Ethertypes.  Any 'single change' notebook page can use this
635  * routine.
636  *
637  * @param notebook_pg A pointer to the "network" notebook page.
638  */
639 static void
640 decode_simple (GtkWidget *notebook_pg)
641 {
642     GtkWidget          *list, *combo_box;
643     GtkTreeSelection   *selection;
644     GtkTreeModel       *model;
645     GtkTreeIter         iter;
646     decode_as_t        *entry;
647     gchar              *table_name, *abbrev;
648     dissector_handle_t  handle;
649     guint               value_loop, *selector_type;
650     gpointer            ptr, value_ptr;
651     gint                requested_index = 0;
652     gboolean            add_reset_list  = FALSE;
653     dissector_table_t   sub_dissectors;
654
655     list = (GtkWidget *)g_object_get_data(G_OBJECT(notebook_pg), E_PAGE_LIST);
656     if (requested_action == E_DECODE_NO)
657         gtk_tree_selection_unselect_all(gtk_tree_view_get_selection(GTK_TREE_VIEW(list)));
658
659     entry = (decode_as_t *)g_object_get_data(G_OBJECT(notebook_pg), E_PAGE_DECODE_AS_DATA);
660     table_name = (gchar *)g_object_get_data(G_OBJECT(notebook_pg), E_PAGE_TABLE);
661     sub_dissectors = find_dissector_table(table_name);
662
663     /* (sub)dissector selection */
664     selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(list));
665     if (gtk_tree_selection_get_selected(selection, &model, &iter) == FALSE)
666     {
667         abbrev = NULL;
668         handle = NULL;
669     } else {
670         gtk_tree_model_get(model, &iter, E_LIST_S_PROTO_NAME, &abbrev,
671                            E_LIST_S_TABLE+1, &handle, -1);
672     }
673
674     if (entry->num_items > 1)
675     {
676         combo_box = (GtkWidget *)g_object_get_data(G_OBJECT(notebook_pg), E_COMBO_BOX_MULTIVALUE);
677         if (!ws_combo_box_get_active_pointer(GTK_COMBO_BOX(combo_box), &ptr))
678             g_assert_not_reached();  /* Programming error if no active item in combo_box */
679         requested_index = GPOINTER_TO_INT(ptr);
680     }
681
682     /* Apply values to dissector table (stored in entry) */
683     for (value_loop = 0; value_loop < entry->values[requested_index].num_values; value_loop++)
684     {
685         pref_t* pref_value;
686         dissector_handle_t  temp_handle;
687         module_t *module;
688
689         guint8 saved_curr_layer_num = cfile.edt->pi.curr_layer_num;
690         cfile.edt->pi.curr_layer_num = (guint8)GPOINTER_TO_UINT(g_object_get_data(G_OBJECT(notebook_pg), E_PAGE_CURR_LAYER_NUM));
691         value_ptr = entry->values[requested_index].build_values[value_loop](&cfile.edt->pi);
692         if (abbrev != NULL && strcmp(abbrev, "(default)") == 0) {
693             /* Find the handle currently associated with the value */
694             temp_handle = dissector_get_uint_handle(sub_dissectors, GPOINTER_TO_UINT(value_ptr));
695
696             add_reset_list = entry->reset_value(table_name, value_ptr);
697
698             /* For now, only numeric dissector tables can use preferences */
699             if (IS_FT_UINT(dissector_table_get_type(sub_dissectors))) {
700                 if (temp_handle != NULL) {
701                     module = prefs_find_module(proto_get_protocol_filter_name(dissector_handle_get_protocol_index(temp_handle)));
702                     pref_value = prefs_find_preference(module, table_name);
703                     if (pref_value != NULL) {
704                         module->prefs_changed = TRUE;
705                         switch(pref_value->type)
706                         {
707                         case PREF_DECODE_AS_UINT:
708                             *pref_value->varp.uint = pref_value->default_val.uint;
709                             break;
710                         case PREF_DECODE_AS_RANGE:
711                             prefs_range_remove_value(pref_value, GPOINTER_TO_UINT(value_ptr));
712                             break;
713                         default:
714                             break;
715                         }
716                     }
717                 }
718             }
719         } else {
720             add_reset_list = entry->change_value(table_name, value_ptr, &handle, abbrev);
721
722             /* For now, only numeric dissector tables can use preferences */
723             if (IS_FT_UINT(dissector_table_get_type(sub_dissectors))) {
724                 module = prefs_find_module(proto_get_protocol_filter_name(dissector_handle_get_protocol_index(handle)));
725                 pref_value = prefs_find_preference(module, table_name);
726                 if (pref_value != NULL) {
727                     module->prefs_changed = TRUE;
728                     switch(pref_value->type)
729                     {
730                     case PREF_DECODE_AS_UINT:
731                         /* This doesn't support multiple values for a dissector in Decode As because the
732                             preference only supports a single value. This leads to a "last port for
733                             dissector in Decode As wins" */
734                         *pref_value->varp.uint = GPOINTER_TO_UINT(value_ptr);
735                         break;
736                     case PREF_DECODE_AS_RANGE:
737                         prefs_range_add_value(pref_value, GPOINTER_TO_UINT(value_ptr));
738                         break;
739                     default:
740                         break;
741                     }
742                 }
743             }
744         }
745         cfile.edt->pi.curr_layer_num = saved_curr_layer_num;
746
747         if (add_reset_list) {
748             selector_type = g_new(guint,1);
749             *selector_type = GPOINTER_TO_UINT(value_ptr);
750             decode_build_reset_list(table_name, FT_UINT32, selector_type, NULL, NULL);
751         }
752     }
753
754     g_free(abbrev);
755 }
756
757
758 /**************************************************/
759 /*      Signals from the "Decode As..." dialog    */
760 /**************************************************/
761
762 /*
763  * This routine is called when the user clicks the "OK" button in the
764  * "Decode As..." dialog window.  This routine calls various helper
765  * routines to set/clear dissector values as requested by the user.
766  * These routines accumulate information on what actions they have
767  * taken, and this summary information is printed by this routine.
768  * This routine then destroys the dialog box and performs other
769  * housekeeping functions.
770  *
771  * @param ok_bt A pointer to the "OK" button.
772  *
773  * @param parent_w A pointer to the dialog window.
774  */
775 static void
776 decode_ok_cb (GtkWidget *ok_bt _U_, gpointer parent_w)
777 {
778     GtkWidget   *notebook, *notebook_pg;
779     void     (* func)(GtkWidget *);
780     gint         page_num;
781     decode_as_t *entry;
782
783     /* Call the right routine for the page that was currently in front. */
784     notebook =  (GtkWidget *)g_object_get_data(G_OBJECT(parent_w), E_NOTEBOOK);
785     page_num = gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook));
786     notebook_pg = gtk_notebook_get_nth_page(GTK_NOTEBOOK(notebook), page_num);
787
788     func = (void (*)(GtkWidget *))g_object_get_data(G_OBJECT(notebook_pg), E_PAGE_ACTION);
789     func(notebook_pg);
790
791     /* Free any values that used dynamic memory */
792     entry = (decode_as_t *)g_object_get_data(G_OBJECT(notebook_pg), E_PAGE_DECODE_AS_DATA);
793     if ((entry->num_items == 1) && (entry->free_func != NULL))
794         entry->free_func(g_object_get_data(G_OBJECT(notebook_pg), E_PAGE_VALUE));
795
796     window_destroy(GTK_WIDGET(parent_w));
797     g_slist_free(decode_dimmable);
798     decode_dimmable = NULL;
799
800     redissect_packets();
801     redissect_all_packet_windows();
802 }
803
804 /*
805  * This routine is called when the user clicks the "Apply" button in the
806  * "Decode As..." dialog window.  This routine calls various helper
807  * routines to set/clear dissector values as requested by the user.
808  * These routines accumulate information on what actions they have
809  * taken, and this summary information is printed by this routine.
810  *
811  * @param apply_bt A pointer to the "Apply" button.
812  *
813  * @param parent_w A pointer to the dialog window.
814  */
815 static void
816 decode_apply_cb (GtkWidget *apply_bt _U_, gpointer parent_w)
817 {
818     GtkWidget *notebook, *notebook_pg;
819     void (* func)(GtkWidget *);
820     gint page_num;
821
822     /* Call the right routine for the page that was currently in front. */
823     notebook =  (GtkWidget *)g_object_get_data(G_OBJECT(parent_w), E_NOTEBOOK);
824     page_num = gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook));
825     notebook_pg = gtk_notebook_get_nth_page(GTK_NOTEBOOK(notebook), page_num);
826
827     func = (void (*)(GtkWidget *))g_object_get_data(G_OBJECT(notebook_pg), E_PAGE_ACTION);
828     func(notebook_pg);
829
830     redissect_packets();
831     redissect_all_packet_windows();
832 }
833
834 /*
835  * This routine is called when the user clicks the "Close" button in
836  * the "Decode As..." dialog window.  This routine then destroys the
837  * dialog box and performs other housekeeping functions.
838  *
839  * @param close_bt A pointer to the "Close" button.
840  *
841  * @param parent_w A pointer to the dialog window.
842  */
843 static void
844 decode_close_cb (GtkWidget *close_bt _U_, gpointer parent_w)
845 {
846     GtkWidget *notebook, *notebook_pg;
847     gint page_num;
848     decode_as_t *entry;
849
850     /* Call the right routine for the page that was currently in front. */
851     notebook =  (GtkWidget *)g_object_get_data(G_OBJECT(parent_w), E_NOTEBOOK);
852     page_num = gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook));
853     notebook_pg = gtk_notebook_get_nth_page(GTK_NOTEBOOK(notebook), page_num);
854
855     /* Free any values that used dynamic memory */
856     entry = (decode_as_t *)g_object_get_data(G_OBJECT(notebook_pg), E_PAGE_DECODE_AS_DATA);
857     if ((entry->num_items == 1) && (entry->free_func != NULL))
858         entry->free_func(g_object_get_data(G_OBJECT(notebook_pg), E_PAGE_VALUE));
859
860     window_destroy(GTK_WIDGET(parent_w));
861     g_slist_free(decode_dimmable);
862     decode_dimmable = NULL;
863 }
864
865
866 /*
867  * This routine is called when the user clicks the "Close" button in
868  * the "Decode As..." dialog window.  This routine simply calls the
869  * close routine as if the user had clicked the close button instead
870  * of the close button.
871  *
872  * @param decode_w_lcl A pointer to the dialog box.
873  *
874  * @param event    A pointer to the GdkEvent struct
875  *
876  * @param user_data Unused
877  */
878 static gboolean
879 decode_delete_cb (GtkWidget *decode_w_lcl, GdkEvent *event _U_, gpointer user_data _U_)
880 {
881     decode_close_cb(NULL, decode_w_lcl);
882     return FALSE;
883 }
884
885
886 /*
887  * This routine is called at the destruction of the "Decode As..."
888  * dialog box.  It clears the pointer maintained by this file, so that
889  * the next time the user selects the "Decode As..." menu item a new
890  * dialog box will be created.
891  *
892  * @param win A pointer to the dialog box.
893  *
894  * @param user_data Unused
895  *
896  * @return void
897  */
898 static void
899 decode_destroy_cb (GtkWidget *win _U_, gpointer user_data _U_)
900 {
901     /* Note that we no longer have a "Decode As" dialog box. */
902     decode_w = NULL;
903 }
904
905
906 /*
907  * This routine is called when the user clicks the "Clear" button in
908  * the "Decode As..." dialog window.  This routine resets all the
909  * dissector values and performs other housekeeping functions.
910  *
911  * @param clear_bt A pointer to the "Clear" button.
912  *
913  * @param user_data Unused
914  */
915 static void
916 decode_clear_cb(GtkWidget *clear_bt _U_, gpointer user_data _U_)
917 {
918     decode_clear_all();
919     redissect_packets();
920     redissect_all_packet_windows();
921 }
922
923
924
925 /**************************************************/
926 /*          Dialog setup - radio buttons          */
927 /**************************************************/
928
929 /*
930  * Update the requested action field of the dialog.  This routine is
931  * called by GTK when either of the two radio buttons in the dialog is
932  * clicked.
933  *
934  * @param w The radio button that was clicked.
935  *
936  * @param user_data The enum value assigned to this radio button.  This
937  * will be either E_DECODE_YES or E_DECODE_NO
938  */
939 static void
940 decode_update_action (GtkWidget *w _U_, gpointer user_data)
941 {
942     GSList   *tmp;
943     gboolean  enable;
944
945     requested_action = (enum action_type)GPOINTER_TO_INT(user_data);
946     enable = (requested_action == E_DECODE_YES);
947     for (tmp = decode_dimmable; tmp; tmp = g_slist_next(tmp)) {
948         gtk_widget_set_sensitive((GtkWidget *)tmp->data, enable);
949     }
950 }
951
952 /*
953  * This routine is called to create the "Decode" and "Do not decode"
954  * radio buttons.  These buttons are installed into a vbox, and set up
955  * as a format group.
956  *
957  * @return GtkWidget * A pointer to the vbox containing the buttons
958  */
959 static GtkWidget *
960 decode_add_yes_no (void)
961 {
962     GtkWidget   *format_vb, *radio_button;
963     GSList      *format_grp;
964
965     format_vb = ws_gtk_box_new(GTK_ORIENTATION_VERTICAL, 2, FALSE);
966
967     radio_button = gtk_radio_button_new_with_label(NULL, "Decode");
968     format_grp = gtk_radio_button_get_group(GTK_RADIO_BUTTON(radio_button));
969     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio_button), TRUE);
970     g_signal_connect(radio_button, "clicked", G_CALLBACK(decode_update_action),
971                    GINT_TO_POINTER(E_DECODE_YES));
972     gtk_box_pack_start(GTK_BOX(format_vb), radio_button, FALSE, FALSE, 0);
973
974     radio_button = gtk_radio_button_new_with_label(format_grp, "Do not decode");
975     g_signal_connect(radio_button, "clicked", G_CALLBACK(decode_update_action),
976                    GINT_TO_POINTER(E_DECODE_NO));
977     gtk_box_pack_start(GTK_BOX(format_vb), radio_button, FALSE, FALSE, 0);
978
979     return(format_vb);
980 }
981
982 /**************************************************/
983 /*          Dialog setup - simple combo_boxes     */
984 /**************************************************/
985
986 /*
987  * This routine is called to pack an combo_box into an aligment, so
988  * that it doesn't expand vertically to fill up the space available to
989  * it.
990  *
991  * @param combo_box A pointer to the option menu to be so packed.
992  *
993  * @return GtkWidget * A pointer to the newly created alignment.
994  */
995 static GtkWidget *
996 decode_add_pack_combo_box (GtkWidget *combo_box)
997 {
998     GtkWidget *alignment;
999
1000     alignment = gtk_alignment_new(0.0f, 0.5f, 0.0f, 0.0f);
1001     gtk_container_add(GTK_CONTAINER(alignment), combo_box);
1002
1003     return(alignment);
1004 }
1005
1006
1007 /*
1008  * This routine is called to add a selection combo_box to
1009  * the dialog box.  The combo_box choices are determined by the dissector.
1010  * The default choice for the combo_box is also determined by the dissector.
1011  *
1012  * @param page A pointer notebook page that will contain all
1013  * widgets created by this routine.
1014  * @param entry Decode As structure used to setup combo_box
1015  *
1016  * @return GtkWidget * A pointer to the newly created alignment into
1017  * which we've packed the newly created combo_box.
1018  */
1019 static GtkWidget *
1020 decode_add_multivalue_combo_box (GtkWidget *page, decode_as_t *entry)
1021 {
1022     GtkWidget *combo_box, *alignment;
1023     guint value;
1024     gchar prompt[MAX_DECODE_AS_PROMPT_LEN];
1025
1026     combo_box = ws_combo_box_new_text_and_pointer();
1027
1028     for (value = 0; value < entry->num_items; value++)
1029     {
1030         entry->values[value].label_func(&cfile.edt->pi, prompt);
1031         ws_combo_box_append_text_and_pointer(GTK_COMBO_BOX(combo_box), prompt, GINT_TO_POINTER(value));
1032     }
1033
1034     ws_combo_box_set_active(GTK_COMBO_BOX(combo_box), entry->default_index_value);
1035     g_object_set_data(G_OBJECT(page), E_COMBO_BOX_MULTIVALUE, combo_box);
1036
1037     alignment = decode_add_pack_combo_box(combo_box);
1038     return(alignment);
1039 }
1040
1041 /*************************************************/
1042 /*        Dialog setup - list based menus        */
1043 /*************************************************/
1044
1045 struct handle_lookup_info {
1046     dissector_handle_t handle;
1047     gboolean           found;
1048 };
1049
1050 static gboolean
1051 lookup_handle(GtkTreeModel *model, GtkTreePath *path _U_, GtkTreeIter *iter,
1052               gpointer user_data)
1053 {
1054     dissector_handle_t handle;
1055     struct handle_lookup_info *hli = (struct handle_lookup_info *)user_data;
1056
1057     gtk_tree_model_get(model, iter, E_LIST_S_TABLE+1, &handle, -1);
1058     if (hli->handle == handle) {
1059         hli->found = TRUE;
1060         return TRUE;
1061     }
1062     return FALSE;
1063 }
1064
1065 /*
1066  * This routine creates one entry in the list of protocol dissector
1067  * that can be used.  It is called by the dissector_table_foreach_handle
1068  * routine once for each entry in a dissector table's list of handles
1069  * for dissectors that could be used in that table.  It guarantees unique
1070  * entries by iterating over the list of entries build up to this point,
1071  * looking for a duplicate name.  If there is no duplicate, then this
1072  * entry is added to the list of possible dissectors.
1073  *
1074  * @param table_name The name of the dissector table currently
1075  * being walked.
1076  *
1077  * @param proto_name The protocol name
1078  *
1079  * @param value The dissector handle for this entry.  This is an opaque
1080  * pointer that can only be handed back to routines in the file packet.c
1081  *
1082  * @param user_data A data block passed into each instance of this
1083  * routine.  It contains information from the caller of the foreach
1084  * routine, specifying information about the dissector table and where
1085  * to store any information generated by this routine.
1086  */
1087 static void
1088 decode_add_to_list (const gchar *table_name, const gchar *proto_name, gpointer value, gpointer user_data)
1089 {
1090     const gchar  *text[E_LIST_S_COLUMNS];
1091     GtkTreeView  *list;
1092     GtkListStore *store;
1093     GtkTreeIter   iter;
1094     struct handle_lookup_info hli;
1095
1096     g_assert(user_data);
1097     g_assert(value);
1098
1099     list = (GtkTreeView *)user_data;
1100
1101     hli.handle = (dissector_handle_t)value;
1102     hli.found = FALSE;
1103     store = GTK_LIST_STORE(gtk_tree_view_get_model(list));
1104     gtk_tree_model_foreach(GTK_TREE_MODEL(store), lookup_handle, &hli);
1105     /* We already have an entry for this handle.
1106      * XXX - will this ever happen? */
1107     if (hli.found) return;
1108
1109     text[E_LIST_S_PROTO_NAME] = proto_name;
1110     text[E_LIST_S_TABLE] = table_name;
1111     gtk_list_store_append(store, &iter);
1112     gtk_list_store_set(store, &iter,
1113                        E_LIST_S_PROTO_NAME, text[E_LIST_S_PROTO_NAME],
1114                        E_LIST_S_TABLE, text[E_LIST_S_TABLE],
1115                        E_LIST_S_TABLE+1, value, -1);
1116 }
1117
1118 static gboolean
1119 decode_list_button_press_cb(GtkWidget *list, GdkEventButton *event, gpointer user_data _U_)
1120 {
1121     if (event->type == GDK_2BUTTON_PRESS) {
1122         GtkWidget *main_w = gtk_widget_get_toplevel(list);
1123
1124         decode_ok_cb (NULL, main_w);
1125     }
1126
1127     return FALSE;
1128 }
1129
1130 static gboolean
1131 decode_list_key_release_cb(GtkWidget *list, GdkEventKey *event, gpointer user_data _U_)
1132 {
1133     if (event->keyval == GDK_Return || event->keyval == GDK_KP_Enter) {
1134         GtkWidget    *main_w = gtk_widget_get_toplevel(list);
1135
1136         decode_ok_cb (NULL, main_w);
1137     }
1138
1139     return FALSE;
1140 }
1141
1142 /*
1143  * This routine starts the creation of a List on a notebook page.  It
1144  * creates both a scrolled window and a list, adds the list to the
1145  * window, and attaches the list as a data object on the page.
1146  *
1147  * @param page A pointer to the notebook page being created.
1148  *
1149  * @param list_p Will be filled in with the address of a newly
1150  * created List.
1151  *
1152  * @param scrolled_win_p Will be filled in with the address of a newly
1153  * created GtkScrolledWindow.
1154  */
1155 static void
1156 decode_list_menu_start(GtkWidget *page, GtkWidget **list_p,
1157                        GtkWidget **scrolled_win_p)
1158 {
1159     GtkTreeView       *list;
1160     GtkListStore      *store;
1161     GtkCellRenderer   *renderer;
1162     GtkTreeViewColumn *tc;
1163     GtkTreeSortable   *sortable;
1164
1165     store = gtk_list_store_new(E_LIST_S_COLUMNS+1, G_TYPE_STRING,
1166                                G_TYPE_STRING, G_TYPE_POINTER);
1167     g_object_set_data(G_OBJECT(decode_w), "sctp_data", store);
1168     list = GTK_TREE_VIEW(tree_view_new(GTK_TREE_MODEL(store)));
1169     g_object_unref(G_OBJECT(store));
1170     sortable = GTK_TREE_SORTABLE(store);
1171     gtk_tree_sortable_set_sort_func(sortable, SORT_ALPHABETICAL, sort_iter_compare_func, GINT_TO_POINTER(SORT_ALPHABETICAL), NULL);
1172     gtk_tree_sortable_set_sort_column_id(sortable, SORT_ALPHABETICAL, GTK_SORT_ASCENDING);
1173     gtk_tree_view_set_headers_clickable(list, FALSE);
1174 #ifndef DEBUG
1175     gtk_tree_view_set_headers_visible(list, FALSE);
1176 #endif
1177     renderer = gtk_cell_renderer_text_new();
1178     tc = gtk_tree_view_column_new_with_attributes("Short Name", renderer,
1179                                                   "text", E_LIST_S_PROTO_NAME,
1180                                                   NULL);
1181     gtk_tree_view_column_set_sizing(tc, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
1182     gtk_tree_view_append_column(list, tc);
1183     g_object_set_data(G_OBJECT(page), E_PAGE_LIST, list);
1184
1185     *scrolled_win_p = scrolled_window_new(NULL, NULL);
1186     /* this will result to set the width of the dialog to the required size */
1187     gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(*scrolled_win_p),
1188                                    GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
1189     gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(*scrolled_win_p),
1190                                    GTK_SHADOW_IN);
1191     gtk_container_add(GTK_CONTAINER(*scrolled_win_p), GTK_WIDGET(list));
1192
1193     *list_p = GTK_WIDGET(list);
1194 }
1195
1196 /*
1197  * This routine finishes the creation of a List on a notebook page.
1198  * It adds the default entry, sets the default entry as the
1199  * highlighted entry, and sorts the List.
1200  *
1201  * @param list A pointer the the List to finish.
1202  */
1203 static void
1204 decode_list_menu_finish(GtkWidget *list)
1205 {
1206     const gchar *text[E_LIST_S_COLUMNS];
1207     GtkListStore *store;
1208     GtkTreeIter   iter;
1209
1210     text[E_LIST_S_PROTO_NAME] = "(default)";
1211     text[E_LIST_S_TABLE] = DECODE_AS_NONE;
1212     store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(list)));
1213     gtk_list_store_prepend(store, &iter);
1214     gtk_list_store_set(store, &iter,
1215                        E_LIST_S_PROTO_NAME, text[E_LIST_S_PROTO_NAME],
1216                        E_LIST_S_TABLE, text[E_LIST_S_TABLE],
1217                        E_LIST_S_TABLE+1, NULL, -1);
1218
1219     gtk_tree_selection_select_iter(gtk_tree_view_get_selection(GTK_TREE_VIEW(list)), &iter);
1220     g_signal_connect(list, "button_press_event", G_CALLBACK(decode_list_button_press_cb), NULL);
1221     g_signal_connect(list, "key_release_event", G_CALLBACK(decode_list_key_release_cb), NULL);
1222 }
1223
1224 /*
1225  * This routine is called to add the dissector selection list to a
1226  * notebook page.  This scrolled list contains an entry labeled
1227  * "default", and an entry for each protocol that has had a dissector
1228  * registered.  The default choice for the list is set to the
1229  * "default" choice, which will return the protocol/port selections to
1230  * their original dissector(s).
1231  *
1232  * @param page A pointer to the notebook page currently being created.
1233  *
1234  * @param entry Decode As structure used to build this (list) menu.
1235  *
1236  * @return GtkWidget * A pointer to the newly created list within a
1237  * scrolled window.
1238  */
1239 static GtkWidget *
1240 decode_add_simple_menu (GtkWidget *page, decode_as_t *entry)
1241 {
1242     GtkWidget *scrolled_window;
1243     GtkWidget *list;
1244
1245     decode_list_menu_start(page, &list, &scrolled_window);
1246     entry->populate_list(entry->table_name, decode_add_to_list, list);
1247     decode_list_menu_finish(list);
1248     return(scrolled_window);
1249 }
1250
1251
1252 /**************************************************/
1253 /*                  Dialog setup                  */
1254 /**************************************************/
1255
1256 /*
1257  * This routine creates a sample notebook page in the dialog box.
1258  * This notebook page provides a prompt specifying what is being
1259  * changed and its current value (e.g. "IP Protocol number (17)"), and
1260  * a list specifying all the available choices.  The list of choices
1261  * is conditionally enabled, based upon the setting of the
1262  * "decode"/"do not decode" radio buttons.
1263  *
1264  * @param entry Decode As structure used to build this page
1265  *
1266  * @return GtkWidget * A pointer to the notebook page created by this
1267  * routine.
1268  */
1269 static GtkWidget *
1270 decode_add_simple_page (decode_as_t *entry)
1271 {
1272     GtkWidget  *page, *label, *scrolled_window, *combo_box;
1273     gchar prompt[MAX_DECODE_AS_PROMPT_LEN];
1274
1275     page = ws_gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 5, FALSE);
1276     g_object_set_data(G_OBJECT(page), E_PAGE_ACTION, decode_simple);
1277     g_object_set_data(G_OBJECT(page), E_PAGE_TABLE, (gchar *) entry->table_name);
1278     g_object_set_data(G_OBJECT(page), E_PAGE_DECODE_AS_DATA, (gchar *)entry);
1279
1280     if (entry->num_items == 1)
1281     {
1282         g_object_set_data(G_OBJECT(page), E_PAGE_VALUE, entry->values[0].build_values[0](&cfile.edt->pi));
1283         g_object_set_data(G_OBJECT(page), E_PAGE_CURR_LAYER_NUM, GUINT_TO_POINTER((guint)cfile.edt->pi.curr_layer_num));
1284
1285         /* Always enabled */
1286         entry->values->label_func(&cfile.edt->pi, prompt);
1287         label = gtk_label_new(prompt);
1288         gtk_box_pack_start(GTK_BOX(page), label, FALSE, FALSE, 0);
1289     }
1290     else
1291     {
1292         /* Always enabled */
1293         if (entry->pre_value_str)
1294         {
1295             label = gtk_label_new(entry->pre_value_str);
1296             gtk_box_pack_start(GTK_BOX(page), label, FALSE, FALSE, 0);
1297         }
1298         combo_box = decode_add_multivalue_combo_box(page, entry);
1299         gtk_box_pack_start(GTK_BOX(page), combo_box, FALSE, FALSE, 0);
1300
1301         if (entry->post_value_str)
1302         {
1303             label = gtk_label_new(entry->post_value_str);
1304             gtk_box_pack_start(GTK_BOX(page), label, FALSE, FALSE, 0);
1305         }
1306     }
1307
1308     /* Conditionally enabled - only when decoding packets */
1309     scrolled_window = decode_add_simple_menu(page, entry);
1310     gtk_box_pack_start(GTK_BOX(page), scrolled_window, TRUE, TRUE, 0);
1311     decode_dimmable = g_slist_prepend(decode_dimmable, scrolled_window);
1312
1313     return(page);
1314 }
1315
1316 /*
1317  * This routine indicates whether we'd actually have any pages in the
1318  * notebook in a "Decode As" dialog box; if there wouldn't be, we
1319  * inactivate the menu item for "Decode As".
1320  */
1321 gboolean
1322 decode_as_ok(void)
1323 {
1324     wmem_list_frame_t *protos = wmem_list_head(cfile.edt->pi.layers);
1325     int                proto_id;
1326     const char*        proto_name;
1327     GList             *list_entry;
1328     decode_as_t       *entry;
1329     dissector_table_t  sub_dissectors;
1330
1331     while (protos != NULL)
1332     {
1333         proto_id = GPOINTER_TO_INT(wmem_list_frame_data(protos));
1334         proto_name = proto_get_protocol_filter_name(proto_id);
1335
1336         list_entry = decode_as_list;
1337         while (list_entry != NULL) {
1338             entry = (decode_as_t *)list_entry->data;
1339             if (!strcmp(proto_name, entry->name))
1340             {
1341                 sub_dissectors = find_dissector_table(entry->table_name);
1342                 if (sub_dissectors != NULL)
1343                     return TRUE;
1344             }
1345
1346             list_entry = g_list_next(list_entry);
1347         }
1348
1349         protos = wmem_list_frame_next(protos);
1350     }
1351
1352     return FALSE;
1353 }
1354
1355
1356 /*
1357  * This routine creates the bulk of the "Decode As" dialog box.  All
1358  * items created by this routine are packed as pages into a notebook.
1359  * There will be a page for each protocol layer that can be changed.
1360  *
1361  * @param format_hb A pointer to the widget in which the notebook
1362  * should be installed.
1363  */
1364 static void
1365 decode_add_notebook (GtkWidget *format_hb)
1366 {
1367     GtkWidget         *notebook, *page, *label;
1368     wmem_list_frame_t *protos = wmem_list_head(cfile.edt->pi.layers);
1369     int                proto_id;
1370     const char*        proto_name;
1371     GList             *list_entry;
1372     decode_as_t       *entry;
1373     guint8             saved_curr_layer_num = cfile.edt->pi.curr_layer_num;
1374
1375     cfile.edt->pi.curr_layer_num = 1;
1376
1377     /* Start a nootbook for flipping between sets of changes */
1378     notebook = gtk_notebook_new();
1379     gtk_box_pack_start(GTK_BOX(format_hb), notebook, TRUE, TRUE, 0);
1380     g_object_set_data(G_OBJECT(decode_w), E_NOTEBOOK, notebook);
1381
1382     while (protos != NULL)
1383     {
1384         proto_id = GPOINTER_TO_INT(wmem_list_frame_data(protos));
1385         proto_name = proto_get_protocol_filter_name(proto_id);
1386
1387         list_entry = decode_as_list;
1388         while (list_entry != NULL) {
1389             entry = (decode_as_t *)list_entry->data;
1390             if (!strcmp(proto_name, entry->name))
1391             {
1392                 if (find_dissector_table(entry->table_name) != NULL)
1393                 {
1394                     page = decode_add_simple_page(entry);
1395                     label = gtk_label_new(entry->title);
1396                     gtk_notebook_append_page(GTK_NOTEBOOK(notebook), page, label);
1397                 }
1398             }
1399
1400             list_entry = g_list_next(list_entry);
1401         }
1402
1403         protos = wmem_list_frame_next(protos);
1404         cfile.edt->pi.curr_layer_num++;
1405     }
1406
1407     cfile.edt->pi.curr_layer_num = saved_curr_layer_num;
1408
1409     /* Select the last added page (selects first by default) */
1410     /* Notebook must be visible for set_page to work. */
1411     gtk_widget_show_all(notebook);
1412     gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook), -1);
1413 }
1414
1415
1416 /*
1417  * This routine creates the "Decode As" dialog box. This dialog box
1418  * asks the user which protocol to use for decoding the currently
1419  * selected packet.  This will affect the last packet that we called a
1420  * dissection routine on belongs (this might be the most recently
1421  * selected packet, or it might be the last packet in the file).
1422  *
1423  * This routine uses an auxiliary function to create the bulk of the
1424  * dialog box, and then hand crafts the button box at the bottom of
1425  * the dialog.
1426  *
1427  * @param w Unused
1428  *
1429  * @param user_data Unused
1430  */
1431 void
1432 decode_as_cb (GtkWidget * w _U_, gpointer user_data _U_)
1433 {
1434     GtkWidget   *main_vb, *format_hb, *bbox, *ok_bt, *close_bt, *help_bt, *button;
1435     GtkWidget   *button_vb, *apply_bt;
1436
1437     if (decode_w != NULL) {
1438         /* There's already a "Decode As" dialog box; reactivate it. */
1439         reactivate_window(decode_w);
1440         return;
1441     }
1442
1443     requested_action = E_DECODE_YES;
1444     decode_w = dlg_window_new("Wireshark: Decode As");
1445     /* Provide a minimum of a couple of rows worth of data */
1446     gtk_window_set_default_size(GTK_WINDOW(decode_w), -1, E_DECODE_MIN_HEIGHT);
1447
1448     /* Container for each row of widgets */
1449     main_vb = ws_gtk_box_new(GTK_ORIENTATION_VERTICAL, 2, FALSE);
1450     gtk_container_set_border_width(GTK_CONTAINER(main_vb), 5);
1451     gtk_container_add(GTK_CONTAINER(decode_w), main_vb);
1452
1453     /* First row - Buttons and Notebook */
1454     format_hb = ws_gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 5, FALSE);
1455     gtk_box_pack_start(GTK_BOX(main_vb), format_hb, TRUE, TRUE, 10);
1456
1457     button_vb = decode_add_yes_no();
1458     gtk_box_pack_start(GTK_BOX(format_hb), button_vb, FALSE, FALSE, 10);
1459
1460     button = gtk_button_new_with_label("Show Current");
1461     g_signal_connect(button, "clicked", G_CALLBACK(decode_show_cb), NULL);
1462     gtk_widget_set_can_default(button, TRUE);
1463     gtk_box_pack_end(GTK_BOX(button_vb), button, FALSE, FALSE, 0);
1464     gtk_widget_set_tooltip_text(button, "Open a dialog showing the current settings.\n"
1465         "Note you need to select and press apply first to be able to save the current setting");
1466
1467     button = ws_gtk_button_new_from_stock(GTK_STOCK_CLEAR);
1468     g_signal_connect(button, "clicked", G_CALLBACK(decode_clear_cb), NULL);
1469     gtk_widget_set_can_default(button, TRUE);
1470     gtk_box_pack_end(GTK_BOX(button_vb), button, FALSE, FALSE, 0);
1471     gtk_widget_set_tooltip_text(button, "Clear ALL settings.");
1472
1473     decode_add_notebook(format_hb);
1474
1475     /* Button row */
1476     bbox = dlg_button_row_new(GTK_STOCK_OK, GTK_STOCK_APPLY, GTK_STOCK_CLOSE, GTK_STOCK_HELP, NULL);
1477     gtk_box_pack_start(GTK_BOX(main_vb), bbox, FALSE, FALSE, 0);
1478     gtk_widget_show(bbox);
1479
1480     ok_bt = (GtkWidget *)g_object_get_data(G_OBJECT(bbox), GTK_STOCK_OK);
1481     g_signal_connect(ok_bt, "clicked", G_CALLBACK(decode_ok_cb), decode_w);
1482     gtk_widget_set_tooltip_text(ok_bt, "Apply current setting, close dialog and redissect packets.");
1483
1484     apply_bt = (GtkWidget *)g_object_get_data(G_OBJECT(bbox), GTK_STOCK_APPLY);
1485     g_signal_connect(apply_bt, "clicked", G_CALLBACK(decode_apply_cb), decode_w);
1486     gtk_widget_set_tooltip_text(apply_bt, "Apply current setting, redissect packets and keep dialog open.");
1487
1488     close_bt = (GtkWidget *)g_object_get_data(G_OBJECT(bbox), GTK_STOCK_CLOSE);
1489     window_set_cancel_button(decode_w, close_bt, NULL);
1490     g_signal_connect(close_bt, "clicked", G_CALLBACK(decode_close_cb), decode_w);
1491     gtk_widget_set_tooltip_text(close_bt, "Close the dialog, don't redissect packets.");
1492
1493     help_bt = (GtkWidget *)g_object_get_data(G_OBJECT(bbox), GTK_STOCK_HELP);
1494     g_signal_connect(help_bt, "clicked", G_CALLBACK(topic_cb), (gpointer)HELP_DECODE_AS_DIALOG);
1495
1496     gtk_widget_grab_default(ok_bt);
1497
1498     g_signal_connect(decode_w, "delete_event", G_CALLBACK(decode_delete_cb), NULL);
1499     g_signal_connect(decode_w, "destroy", G_CALLBACK(decode_destroy_cb), NULL);
1500
1501     gtk_widget_show_all(decode_w);
1502     window_present(decode_w);
1503 }
1504
1505 /*
1506  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
1507  *
1508  * Local variables:
1509  * c-basic-offset: 4
1510  * tab-width: 8
1511  * indent-tabs-mode: nil
1512  * End:
1513  *
1514  * vi: set shiftwidth=4 tabstop=8 expandtab:
1515  * :indentSize=4:tabSize=8:noTabs=true:
1516  */