More eradication of old-style function definitions.
[obnox/wireshark/wip.git] / gtk / expert_comp_dlg.c
1 /* expert_comp_dlg.c
2  * expert_comp_dlg   2005 Greg Morris
3  *
4  * $Id$
5  *
6  * Wireshark - Network traffic analyzer
7  * By Gerald Combs <gerald@wireshark.org>
8  * Copyright 1998 Gerald Combs
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License
12  * as published by the Free Software Foundation; either version 2
13  * of the License, or (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
23  */
24
25 #ifdef HAVE_CONFIG_H
26 # include "config.h"
27 #endif
28
29 #ifdef HAVE_SYS_TYPES_H
30 # include <sys/types.h>
31 #endif
32 #include <string.h>
33
34 #include <gtk/gtk.h>
35
36 #include <epan/packet_info.h>
37 #include <epan/tap.h>
38 #include <epan/stat_cmd_args.h>
39 #include <epan/prefs.h>
40
41 #include "../simple_dialog.h"
42 #include "../stat_menu.h"
43
44 #include "gtk/gui_utils.h"
45 #include "gtk/dlg_utils.h"
46 #include "gtk/expert_comp_table.h"
47 #include "gtk/gui_stat_menu.h"
48 #include "gtk/help_dlg.h"
49 #include "gtk/expert_comp_dlg.h"
50 #include "gtk/stock_icons.h"
51 #include "gtk/main.h"
52
53 #include "gtk/main_proto_draw.h"
54
55
56 enum
57 {
58     NO_COLUMN,
59     SEVERITY_COLUMN,
60     GROUP_COLUMN,
61     PROTOCOL_COLUMN,
62     SUMMARY_COLUMN,
63     FOREGROUND_COLOR_COL,
64     BACKGROUND_COLOR_COL,
65     N_COLUMNS
66 };
67
68 /* used to keep track of the statistics for an entire program interface */
69 typedef struct _expert_comp_dlg_t {
70     GtkWidget *win;
71     GtkWidget *chat_label;
72     GtkWidget *note_label;
73     GtkWidget *warn_label;
74     GtkWidget *error_label;
75     GtkWidget *all_label;
76     error_equiv_table chat_table;
77     error_equiv_table note_table;
78     error_equiv_table warn_table;
79     error_equiv_table error_table;
80     guint32 disp_events;
81     guint32 chat_events;
82     guint32 note_events;
83     guint32 warn_events;
84     guint32 error_events;
85 } expert_comp_dlg_t;
86
87 struct expert_tapdata_s {
88         GtkWidget       *win;
89         GtkWidget       *scrolled_window;
90         GtkTreeView *tree_view;
91         GtkWidget       *label;
92         guint32         disp_events;
93         guint32         chat_events;
94         guint32         note_events;
95         guint32         warn_events;
96         guint32         error_events;
97         int             severity_report_level;
98
99         GArray          *ei_array;      /* expert info items */
100         guint           first;
101         guint           last;
102         GStringChunk*   text;           /* summary text */
103 };
104
105 static GtkWidget  *expert_comp_dlg_w = NULL;
106
107 static void
108 select_row_cb(GtkTreeSelection *selection, gpointer *user_data _U_)
109 {
110     /*guint num = GPOINTER_TO_UINT(gtk_clist_get_row_data(clist, row));*/
111
112     /*cf_goto_frame(&cfile, num);*/
113
114     GtkTreeIter iter;
115     GtkTreeModel *model;
116     guint fnumber;
117
118     if (selection==NULL)
119         return;
120
121     if (gtk_tree_selection_get_selected (selection, &model, &iter)){
122         gtk_tree_model_get (model, &iter, NO_COLUMN, &fnumber, -1);
123         cf_goto_frame(&cfile, fnumber);
124     }
125
126 }
127
128 /* reset of display only, e.g. for filtering */
129 static void expert_dlg_display_reset(expert_tapdata_t * etd)
130 {
131     etd->disp_events = 0;
132     gtk_list_store_clear(GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(etd->tree_view))));
133
134     gtk_window_set_title(GTK_WINDOW(etd->win), "Wireshark: ? Expert Infos");
135     if(etd->label) {
136         gtk_label_set_text(GTK_LABEL(etd->label), "Please wait ...");
137     }
138 }
139
140 /* complete reset, e.g. capture file closed */
141 static void 
142 expert_dlg_reset(void *tapdata)
143 {
144     expert_tapdata_t * etd = tapdata;
145
146     etd->chat_events = 0;
147     etd->note_events = 0;
148     etd->warn_events = 0;
149     etd->error_events = 0;
150     etd->last = 0;
151     etd->first = 0;
152     /* g_string_chunk_clear() is introduced in glib 2.14 */
153     g_string_chunk_free(etd->text);
154     etd->text = g_string_chunk_new(100);
155     g_array_set_size(etd->ei_array, 0);
156
157     expert_dlg_display_reset(etd);
158 }
159
160 static int 
161 expert_dlg_packet(void *tapdata, packet_info *pinfo _U_, epan_dissect_t *edt _U_, const void *pointer)
162 {
163     expert_info_t    *ei;
164     expert_tapdata_t *etd = tapdata;
165
166     g_array_append_val(etd->ei_array, *(expert_info_t *)pointer);
167     etd->last = etd->ei_array->len;
168     ei = &g_array_index(etd->ei_array, expert_info_t, etd->last -1); /* ugly */
169     ei->protocol = g_string_chunk_insert_const(etd->text, ei->protocol);
170     ei->summary = g_string_chunk_insert_const(etd->text, ei->summary);
171
172     switch(ei->severity) {
173     case(PI_CHAT):
174         etd->chat_events++;
175         break;
176     case(PI_NOTE):
177         etd->note_events++;
178         break;
179     case(PI_WARN):
180         etd->warn_events++;
181         break;
182     case(PI_ERROR):
183         etd->error_events++;
184         break;
185     default:
186         g_assert_not_reached();
187     }
188     if(ei->severity < etd->severity_report_level) {
189         return 0; /* draw not required */
190     } else {
191         return 1; /* draw required */
192     }
193 }
194 static void
195 error_set_title(expert_comp_dlg_t *ss)
196 {
197     char *title;
198
199     title = g_strdup_printf("Expert Info Composite: %s",
200         cf_get_display_name(&cfile));
201     gtk_window_set_title(GTK_WINDOW(ss->win), title);
202     g_free(title);
203 }
204
205 static void
206 error_reset(void *pss)
207 {
208     expert_comp_dlg_t *ss=(expert_comp_dlg_t *)pss;
209     gchar *buf;
210
211     ss->error_events = 0;
212     ss->warn_events = 0;
213     ss->note_events = 0;
214     ss->chat_events = 0;
215     ss->disp_events = 0;
216
217     reset_error_table_data(&ss->error_table);
218     buf = g_strdup_printf("Errors: %u (0)", ss->error_table.num_procs);
219     gtk_label_set_text( GTK_LABEL(ss->error_label), buf);
220     g_free(buf);
221
222     reset_error_table_data(&ss->warn_table);
223     buf = g_strdup_printf("Warnings: %u (0)", ss->warn_table.num_procs);
224     gtk_label_set_text( GTK_LABEL(ss->warn_label), buf);
225     g_free(buf);
226
227     reset_error_table_data(&ss->note_table);
228     buf = g_strdup_printf("Notes: %u (0)", ss->note_table.num_procs);
229     gtk_label_set_text( GTK_LABEL(ss->note_label), buf);
230     g_free(buf);
231
232     reset_error_table_data(&ss->chat_table);
233     buf = g_strdup_printf("Chats: %u (0)", ss->chat_table.num_procs);
234     gtk_label_set_text( GTK_LABEL(ss->chat_label), buf);
235     g_free(buf);
236
237     gtk_label_set_text( GTK_LABEL(ss->all_label), "Details: 0");
238     error_set_title(ss);
239 }
240
241 static gboolean
242 error_packet(void *pss, packet_info *pinfo _U_, epan_dissect_t *edt _U_, const void *prv)
243 {
244     expert_comp_dlg_t *ss=(expert_comp_dlg_t *)pss;
245     const expert_info_t *error_pkt=prv;
246
247     /* if return value is 0 then no error */
248     if(error_pkt==NULL){
249         return FALSE;
250     }
251
252     switch (error_pkt->severity) {
253     case PI_ERROR:
254         ss->disp_events++;
255         ss->error_events++;
256         init_error_table_row(&ss->error_table, error_pkt);
257         break;
258     case PI_WARN:
259         ss->disp_events++;
260         ss->warn_events++;
261         init_error_table_row(&ss->warn_table, error_pkt);
262         break;
263     case PI_NOTE:
264         ss->disp_events++;
265         ss->note_events++;
266         init_error_table_row(&ss->note_table, error_pkt);
267         break;
268     case PI_CHAT:
269         ss->disp_events++;
270         ss->chat_events++;
271         init_error_table_row(&ss->chat_table, error_pkt);
272         break;
273     default:
274         return FALSE; /* Don't draw */
275     }
276     return TRUE; /* Draw */
277 }
278
279 static void
280 expert_comp_draw(void *data)
281 {
282     gchar *buf = NULL;
283
284     expert_comp_dlg_t *ss=(expert_comp_dlg_t *)data;
285
286     buf = g_strdup_printf("Errors: %u (%u)", ss->error_table.num_procs, ss->error_events);
287     gtk_label_set_text( GTK_LABEL(ss->error_label), buf);
288     g_free(buf);
289
290     buf = g_strdup_printf("Warnings: %u (%u)", ss->warn_table.num_procs, ss->warn_events);
291     gtk_label_set_text( GTK_LABEL(ss->warn_label), buf);
292     g_free(buf);
293
294     buf = g_strdup_printf("Notes: %u (%u)", ss->note_table.num_procs, ss->note_events);
295     gtk_label_set_text( GTK_LABEL(ss->note_label), buf);
296     g_free(buf);
297
298     buf = g_strdup_printf("Chats: %u (%u)", ss->chat_table.num_procs, ss->chat_events);
299     gtk_label_set_text( GTK_LABEL(ss->chat_label), buf);
300     g_free(buf);
301
302     buf = g_strdup_printf("Details: %u", ss->disp_events);
303     gtk_label_set_text( GTK_LABEL(ss->all_label), buf);
304     g_free(buf);
305
306 }
307
308 static void
309 win_destroy_cb(GtkWindow *win _U_, gpointer data)
310 {
311     expert_comp_dlg_t *ss=(expert_comp_dlg_t *)data;
312
313     protect_thread_critical_region();
314     remove_tap_listener(ss);
315     unprotect_thread_critical_region();
316
317     if (expert_comp_dlg_w != NULL) {
318         window_destroy(expert_comp_dlg_w);
319         expert_comp_dlg_w = NULL;
320     }
321
322     free_error_table_data(&ss->error_table);
323     free_error_table_data(&ss->warn_table);
324     free_error_table_data(&ss->note_table);
325     free_error_table_data(&ss->chat_table);
326     g_free(ss);
327
328 }
329
330 static void
331 expert_dlg_destroy_cb(GtkWindow *win _U_, gpointer data)
332 {
333     expert_tapdata_t *etd=(expert_tapdata_t *)data;
334
335     protect_thread_critical_region();
336     remove_tap_listener(etd);
337     unprotect_thread_critical_region();
338
339     /*free_srt_table_data(&etd->afp_srt_table);*/
340     g_array_free(etd->ei_array, TRUE);
341     g_string_chunk_free(etd->text);
342     g_free(etd);
343 }
344
345 static expert_tapdata_t * expert_dlg_new_table(void)
346 {
347     expert_tapdata_t * etd;
348     etd=g_malloc0(sizeof(expert_tapdata_t));
349
350     etd->ei_array = g_array_sized_new(FALSE, FALSE, sizeof(expert_info_t), 1000);
351     etd->text = g_string_chunk_new(100);
352     etd->severity_report_level = PI_CHAT;
353     return etd;
354 }
355
356 static void
357 expert_dlg_init_table(expert_tapdata_t * etd, GtkWidget *vbox)
358 {
359     GtkListStore *store;
360     GtkWidget *tree;
361     GtkTreeViewColumn *column;
362     GtkCellRenderer *renderer;
363     GtkTreeSortable *sortable;
364     GtkTreeSelection  *selection;
365
366     /* Create the store */
367     store = gtk_list_store_new(N_COLUMNS,        /* Total number of columns */
368                                G_TYPE_UINT,      /* No                   */
369                                G_TYPE_POINTER,   /* Severity           */
370                                G_TYPE_POINTER,   /* Group              */
371                                G_TYPE_POINTER,    /* Protocol           */
372                                G_TYPE_POINTER,    /* Summary            */
373                                G_TYPE_STRING,    /* forground          */
374                                G_TYPE_STRING);   /* Background         */
375
376     /* Create a view */
377     tree = gtk_tree_view_new_with_model (GTK_TREE_MODEL (store));
378     etd->tree_view = GTK_TREE_VIEW(tree);
379     sortable = GTK_TREE_SORTABLE(store);
380
381 #if GTK_CHECK_VERSION(2,6,0)
382     /* Speed up the list display */
383     gtk_tree_view_set_fixed_height_mode(etd->tree_view, TRUE);
384 #endif
385
386     /* Setup the sortable columns */
387     gtk_tree_view_set_headers_clickable(GTK_TREE_VIEW (tree), FALSE);
388
389     /* The view now holds a reference.  We can get rid of our own reference */
390     g_object_unref (G_OBJECT (store));
391
392     /* Let the font be the default one to have the same look as the rest of the tabs
393          * Bug https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=4388
394          * gtk_widget_modify_font(GTK_WIDGET (etd->tree_view), user_font_get_regular());
395          */
396
397     /* Create a cell renderer */
398     renderer = gtk_cell_renderer_text_new ();
399     g_object_set(renderer, "ypad", 0, NULL);
400     g_object_set(renderer, "xalign", 1.0, NULL);
401
402     /* Create the first column, associating the "text" attribute of the
403      * cell_renderer to the first column of the model */
404     /* No */
405     column = gtk_tree_view_column_new_with_attributes ("No", renderer,
406         "text", NO_COLUMN,
407         "foreground", FOREGROUND_COLOR_COL,
408         "background", BACKGROUND_COLOR_COL,
409         NULL);
410     gtk_tree_view_column_set_sort_column_id(column, NO_COLUMN);
411     gtk_tree_view_column_set_resizable(column, TRUE);
412     gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
413     gtk_tree_view_column_set_min_width(column, 80);
414     gtk_tree_view_append_column (etd->tree_view, column);
415
416     /* Severity */
417     renderer = gtk_cell_renderer_text_new ();
418     g_object_set(renderer, "ypad", 0, NULL);
419
420     column = gtk_tree_view_column_new_with_attributes ("Severity", renderer,
421         "foreground", FOREGROUND_COLOR_COL,
422         "background", BACKGROUND_COLOR_COL,
423         NULL);
424
425         gtk_tree_view_column_set_cell_data_func(column, renderer, str_ptr_data_func,
426                 GINT_TO_POINTER(SEVERITY_COLUMN), NULL);
427
428         gtk_tree_sortable_set_sort_func(sortable, SEVERITY_COLUMN, str_ptr_sort_func,
429                 GINT_TO_POINTER(SEVERITY_COLUMN), NULL);
430
431     gtk_tree_view_column_set_sort_column_id(column, SEVERITY_COLUMN);
432     gtk_tree_view_column_set_resizable(column, TRUE);
433     gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
434     gtk_tree_view_column_set_min_width(column, 80);
435     /* Add the column to the view. */
436     gtk_tree_view_append_column (etd->tree_view, column);
437
438     /* Group */
439     renderer = gtk_cell_renderer_text_new ();
440     g_object_set(renderer, "ypad", 0, NULL);
441     column = gtk_tree_view_column_new_with_attributes ("Group", renderer,
442         "foreground", FOREGROUND_COLOR_COL,
443         "background", BACKGROUND_COLOR_COL,
444         NULL);
445
446         gtk_tree_view_column_set_cell_data_func(column, renderer, str_ptr_data_func,
447                 GINT_TO_POINTER(GROUP_COLUMN), NULL);
448
449         gtk_tree_sortable_set_sort_func(sortable, GROUP_COLUMN, str_ptr_sort_func,
450                 GINT_TO_POINTER(GROUP_COLUMN), NULL);
451
452     gtk_tree_view_column_set_sort_column_id(column, GROUP_COLUMN);
453     gtk_tree_view_column_set_resizable(column, TRUE);
454     gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
455     gtk_tree_view_column_set_min_width(column, 80);
456     /* Add the column to the view. */
457     gtk_tree_view_append_column (etd->tree_view, column);
458
459     /* Protocol. */
460     renderer = gtk_cell_renderer_text_new ();
461     g_object_set(renderer, "ypad", 0, NULL);
462     column = gtk_tree_view_column_new_with_attributes ("Protocol", renderer,
463         "foreground", FOREGROUND_COLOR_COL,
464         "background", BACKGROUND_COLOR_COL,
465         NULL);
466         gtk_tree_view_column_set_cell_data_func(column, renderer, str_ptr_data_func,
467                 GINT_TO_POINTER(PROTOCOL_COLUMN), NULL);
468
469         gtk_tree_sortable_set_sort_func(sortable, PROTOCOL_COLUMN, str_ptr_sort_func,
470                 GINT_TO_POINTER(PROTOCOL_COLUMN), NULL);
471
472     gtk_tree_view_column_set_sort_column_id(column, PROTOCOL_COLUMN);
473     gtk_tree_view_column_set_resizable(column, TRUE);
474     gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
475     gtk_tree_view_column_set_min_width(column, 80);
476     gtk_tree_view_append_column (etd->tree_view, column);
477
478     /* Summary. */
479     renderer = gtk_cell_renderer_text_new ();
480     g_object_set(renderer, "ypad", 0, NULL);
481     column = gtk_tree_view_column_new_with_attributes ("Summary", renderer,
482         "foreground", FOREGROUND_COLOR_COL,
483         "background", BACKGROUND_COLOR_COL,
484         NULL);
485         gtk_tree_view_column_set_cell_data_func(column, renderer, str_ptr_data_func,
486                 GINT_TO_POINTER(SUMMARY_COLUMN), NULL);
487
488         gtk_tree_sortable_set_sort_func(sortable, SUMMARY_COLUMN, str_ptr_sort_func,
489                 GINT_TO_POINTER(SUMMARY_COLUMN), NULL);
490
491     gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
492     gtk_tree_view_column_set_min_width(column, 90);
493     gtk_tree_view_column_set_sort_column_id(column, SUMMARY_COLUMN);
494     gtk_tree_view_column_set_resizable(column, TRUE);
495     gtk_tree_view_append_column (etd->tree_view, column);
496
497
498     gtk_tree_view_set_search_column (etd->tree_view, SUMMARY_COLUMN); /* Allow searching the summary */
499     gtk_tree_view_set_reorderable (etd->tree_view, TRUE);   /* Allow user to reorder data with drag n drop */
500
501     /* Now enable the sorting of each column */
502     gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(etd->tree_view), TRUE);
503     gtk_tree_view_set_headers_clickable(GTK_TREE_VIEW(etd->tree_view), TRUE);
504
505     /* Setup the selection handler */
506     selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(etd->tree_view));
507     gtk_tree_selection_set_mode(selection, GTK_SELECTION_SINGLE);
508
509     g_signal_connect (G_OBJECT (selection), "changed", /* select_row */
510                   G_CALLBACK (select_row_cb),
511                   NULL);
512
513     etd->scrolled_window=scrolled_window_new(NULL, NULL);
514     gtk_container_add(GTK_CONTAINER(etd->scrolled_window), GTK_WIDGET (etd->tree_view));
515
516     gtk_box_pack_start(GTK_BOX(vbox), etd->scrolled_window, TRUE, TRUE, 0);
517 }
518
519 static void
520 expert_dlg_draw(void *data)
521 {
522     expert_tapdata_t *etd = data;
523     expert_info_t *ei;
524     gchar *title;
525     const char *entries[2];   /**< column entries */
526     GtkListStore *list_store;
527     GtkTreeIter iter;
528     gchar *color_str = NULL;
529     guint packet_no = 0;
530         const gchar *group_str;
531         const gchar *severity_str;
532
533
534     if(etd->label) {
535         if(etd->last - etd->first) {
536             title = g_strdup_printf("Adding: %u new messages",etd->last - etd->first);
537             gtk_label_set_text(GTK_LABEL(etd->label), title);
538             g_free(title);
539         }
540     }
541
542     /* append new events (remove from new list, append to displayed list and clist) */
543     while(etd->first < etd->last){
544         ei = &g_array_index(etd->ei_array, expert_info_t, etd->first);
545         etd->first++;
546
547         if(ei->severity < etd->severity_report_level) {
548             continue;
549         }
550         etd->disp_events++;
551
552         /* packet number */
553         if(ei->packet_num) {
554             packet_no = ei->packet_num;
555         }
556
557         /*  match_strval return a static string or NULL
558             severity */
559                 severity_str = match_strval(ei->severity, expert_severity_vals);
560         /* group */
561                 group_str = match_strval(ei->group, expert_group_vals);
562
563         /* protocol */
564         if(ei->protocol) {
565             entries[0] = ei->protocol;
566         } else {
567             entries[0] = "-";
568         }
569
570         /* summary */
571         entries[1] = ei->summary;
572
573         /* set rows background color depending on severity */
574         switch(ei->severity) {
575         case(PI_CHAT):
576             color_str = expert_color_chat_str;
577             break;
578         case(PI_NOTE):
579             color_str = expert_color_note_str;
580             break;
581         case(PI_WARN):
582             color_str = expert_color_warn_str;
583             break;
584         case(PI_ERROR):
585             color_str = expert_color_error_str;
586             break;
587         default:
588             g_assert_not_reached();
589         }
590
591         list_store = GTK_LIST_STORE(gtk_tree_view_get_model(etd->tree_view)); /* Get store */
592
593         /* Creates a new row at position. iter will be changed to point to this new row.
594          * If position is larger than the number of rows on the list, then the new row will be appended to the list.
595          * The row will be filled with the values given to this function.
596          * :
597          * should generally be preferred when inserting rows in a sorted list store.
598          */
599 #if GTK_CHECK_VERSION(2,6,0)
600         gtk_list_store_insert_with_values( list_store , &iter, G_MAXINT,
601 #else
602         gtk_list_store_append  (list_store, &iter);
603         gtk_list_store_set  (list_store, &iter,
604 #endif
605                     NO_COLUMN, packet_no,
606                     SEVERITY_COLUMN, severity_str,
607                     GROUP_COLUMN, group_str,
608                     PROTOCOL_COLUMN, entries[0],
609                     SUMMARY_COLUMN, entries[1],
610                     FOREGROUND_COLOR_COL, expert_color_foreground_str,
611                     BACKGROUND_COLOR_COL, color_str,
612                     -1);
613     }
614
615     if(etd->label) {
616         title = g_strdup_printf("Errors: %u Warnings: %u Notes: %u Chats: %u",
617                                 etd->error_events, etd->warn_events,
618                                 etd->note_events, etd->chat_events);
619         gtk_label_set_text(GTK_LABEL(etd->label), title);
620         g_free(title);
621     }
622
623     title = g_strdup_printf("Wireshark: %u Expert Info%s",
624                             etd->disp_events,
625                             plurality(etd->disp_events, "", "s"));
626     gtk_window_set_title(GTK_WINDOW(etd->win), title);
627     g_free(title);
628 }
629
630 static void
631 expert_comp_init(const char *optarg _U_, void* userdata _U_)
632 {
633     expert_comp_dlg_t *ss;
634     const char *filter=NULL;
635     GString *error_string;
636     GtkWidget *temp_page;
637     GtkWidget *main_nb;
638     GtkWidget *vbox;
639     GtkWidget *hbox;
640     GtkWidget *bbox;
641     GtkWidget *close_bt;
642     GtkWidget *help_bt;
643     expert_tapdata_t *etd;
644     GtkTooltips *tooltips = gtk_tooltips_new();
645
646     ss=g_malloc(sizeof(expert_comp_dlg_t));
647
648     ss->disp_events = 0;
649     ss->chat_events = 0;
650     ss->note_events = 0;
651     ss->warn_events = 0;
652     ss->error_events = 0;
653
654     expert_comp_dlg_w = ss->win=dlg_window_new("err");  /* transient_for top_level */
655     gtk_window_set_destroy_with_parent (GTK_WINDOW(ss->win), TRUE);
656     gtk_window_set_default_size(GTK_WINDOW(ss->win), 700, 300);
657
658     error_set_title(ss);
659
660     vbox=gtk_vbox_new(FALSE, 3);
661     gtk_container_add(GTK_CONTAINER(ss->win), vbox);
662     gtk_container_set_border_width(GTK_CONTAINER(vbox), 12);
663
664     main_nb = gtk_notebook_new();
665     gtk_box_pack_start(GTK_BOX(vbox), main_nb, TRUE, TRUE, 0);
666
667     /* We must display TOP LEVEL Widget before calling init_table() */
668     gtk_widget_show_all(ss->win);
669
670     /* Errors */
671     temp_page = gtk_vbox_new(FALSE, 6);
672     ss->error_label = gtk_label_new("Errors: 0/y");
673     gtk_widget_show(ss->error_label);
674     hbox = gtk_hbox_new(FALSE, 3);
675     gtk_container_add(GTK_CONTAINER(hbox), ss->error_label);
676     gtk_notebook_append_page(GTK_NOTEBOOK(main_nb), temp_page, hbox);
677     init_error_table(&ss->error_table, 0, temp_page);
678
679     /* Warnings */
680     temp_page = gtk_vbox_new(FALSE, 6);
681     ss->warn_label = gtk_label_new("Warnings: 0/y");
682     gtk_widget_show(ss->warn_label);
683     hbox = gtk_hbox_new(FALSE, 3);
684     gtk_container_add(GTK_CONTAINER(hbox), ss->warn_label);
685     gtk_notebook_append_page(GTK_NOTEBOOK(main_nb), temp_page, hbox);
686     init_error_table(&ss->warn_table, 0, temp_page);
687
688     /* Notes */
689     temp_page = gtk_vbox_new(FALSE, 6);
690     ss->note_label = gtk_label_new("Notes: 0/y");
691     gtk_widget_show(ss->note_label);
692     hbox = gtk_hbox_new(FALSE, 3);
693     gtk_container_add(GTK_CONTAINER(hbox), ss->note_label);
694     gtk_notebook_append_page(GTK_NOTEBOOK(main_nb), temp_page, hbox);
695     init_error_table(&ss->note_table, 0, temp_page);
696
697     /* Chat */
698     temp_page = gtk_vbox_new(FALSE, 6);
699     ss->chat_label = gtk_label_new("Chats: 0/y");
700     gtk_widget_show(ss->chat_label);
701     hbox = gtk_hbox_new(FALSE, 3);
702     gtk_container_add(GTK_CONTAINER(hbox), ss->chat_label);
703     gtk_notebook_append_page(GTK_NOTEBOOK(main_nb), temp_page, hbox);
704     init_error_table(&ss->chat_table, 0, temp_page);
705
706     /* Details */
707     temp_page = gtk_vbox_new(FALSE, 6);
708     ss->all_label = gtk_label_new("Details: 0");
709     gtk_notebook_append_page(GTK_NOTEBOOK(main_nb), temp_page, ss->all_label);
710
711     etd = expert_dlg_new_table();
712     etd->label=gtk_label_new("Please wait ...");
713     gtk_misc_set_alignment(GTK_MISC(etd->label), 0.0f, 0.5f);
714
715     etd->win=ss->win;
716     expert_dlg_init_table(etd, temp_page);
717
718     /* Add tap listener functions for expert details, From expert_dlg.c*/
719     error_string=register_tap_listener("expert", etd, NULL /* fstring */,
720                                        TL_REQUIRES_PROTO_TREE,
721                                        expert_dlg_reset,
722                                        expert_dlg_packet,
723                                        expert_dlg_draw);
724     if(error_string){
725         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", error_string->str);
726         g_string_free(error_string, TRUE);
727         g_free(etd);
728         return;
729     }
730
731     g_signal_connect(etd->win, "delete_event", G_CALLBACK(window_delete_event_cb), NULL);
732     g_signal_connect(etd->win, "destroy", G_CALLBACK(expert_dlg_destroy_cb), etd);
733
734     /* Register the tap listener */
735
736     error_string=register_tap_listener("expert", ss, filter, 0, error_reset, error_packet, expert_comp_draw);
737     if(error_string){
738         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", error_string->str);
739         g_string_free(error_string, TRUE);
740         g_free(ss);
741         return;
742     }
743
744     /* Button row. */
745     bbox = dlg_button_row_new(GTK_STOCK_CLOSE, GTK_STOCK_HELP, NULL);
746     gtk_box_pack_end(GTK_BOX(vbox), bbox, FALSE, FALSE, 0);
747
748     close_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_CLOSE);
749     window_set_cancel_button(ss->win, close_bt, window_cancel_button_cb);
750
751     help_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_HELP);
752     g_signal_connect(help_bt, "clicked", G_CALLBACK(topic_cb), (gpointer)HELP_EXPERT_INFO_DIALOG);
753     gtk_tooltips_set_tip (tooltips, help_bt, "Show topic specific help", NULL);
754
755     g_signal_connect(ss->win, "delete_event", G_CALLBACK(window_delete_event_cb), NULL);
756     g_signal_connect(ss->win, "destroy", G_CALLBACK(win_destroy_cb), ss);
757
758     gtk_widget_show_all(ss->win);
759     window_present(ss->win);
760
761     /*
762      * At least at present, the only information the tap listener appears
763      * to care about is available regardless of whether the protocol tree
764      * is being built, so we don't appear to need to have the protocol
765      * tree built.
766      *
767      * This means we can use cf_retap_packets(), even though it will only
768      * build the protocol tree if at least one tap has a filter in place.
769      * cf_retap_packets() is faster than cf_redissect_packets(), as it
770      * assumes we didn't change anything that would cause any packets to
771      * dissect differently, and thus doesn't redo the packet display.
772      */
773     cf_retap_packets(&cfile);
774
775     /* This will bring up the progress bar
776      * Put our window back in front
777      */
778     gdk_window_raise(ss->win->window);
779     /* Set the lable text */
780     expert_comp_draw(ss);
781 }
782
783 void
784 expert_comp_dlg_launch(void)
785 {
786     if (expert_comp_dlg_w) {
787         reactivate_window(expert_comp_dlg_w);
788     } else {
789         expert_comp_init("", NULL);
790     }
791 }
792
793 void
794 register_tap_listener_expert_comp(void)
795 {
796     register_stat_cmd_arg("expert_comp", expert_comp_init,NULL);
797 #ifdef MAIN_MENU_USE_UIMANAGER
798 #else
799     register_stat_menu_item_stock("Expert Info _Composite",
800         REGISTER_ANALYZE_GROUP_UNSORTED, WIRESHARK_STOCK_EXPERT_INFO,
801         expert_comp_dlg_launch, NULL, NULL, NULL);
802 #endif
803 }