I added the byte count to the Data section. The print routines had to
[obnox/wireshark/wip.git] / ethereal.c
1 /* ethereal.c
2  *
3  * $Id: ethereal.c,v 1.8 1998/10/16 06:44:32 guy Exp $
4  *
5  * Ethereal - Network traffic analyzer
6  * By Gerald Combs <gerald@zing.org>
7  * Copyright 1998 Gerald Combs
8  *
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  * To do:
26  * - Live browser/capture display
27  * - Graphs
28  * - Get AIX to work
29  * - Check for end of packet in dissect_* routines.
30  * - Playback window
31  * - Multiple window support
32  * - Add cut/copy/paste
33  * - Handle snoop files
34  * - Fix progress/status bar glitches?  (GTK+ bug?)
35  * - Create header parsing routines
36  * - Check fopens, freads, fwrites
37  * - Make byte view scrollbars automatic?
38  * - Make byte view selections more fancy?
39  *
40  */
41
42 #ifdef HAVE_CONFIG_H
43 # include "config.h"
44 #endif
45
46 #include <gtk/gtk.h>
47 #include <pcap.h>
48
49 #include <stdio.h>
50 #include <string.h>
51 #include <unistd.h>
52 #include <sys/types.h>
53 #include <sys/stat.h>
54 #include <fcntl.h>
55 #include <netinet/in.h>
56
57 #include "ethereal.h"
58 #include "capture.h"
59 #include "packet.h"
60 #include "file.h"
61 #include "menu.h"
62 #include "etypes.h"
63 #include "print.h"
64 #include "resolv.h"
65 #include "follow.h"
66 #include "util.h"
67 #include "prefs.h"
68
69 FILE        *data_out_file = NULL;
70 packet_info  pi;
71 capture_file cf;
72 GtkWidget   *file_sel, *packet_list, *tree_view, *byte_view, *prog_bar,
73             *info_bar;
74 GdkFont     *m_r_font, *m_b_font;
75 guint        main_ctx, file_ctx;
76 frame_data  *fd;
77 gint         start_capture = 0;
78
79 extern pr_opts printer_opts;
80
81 ts_type timestamp_type = RELATIVE;
82
83 #define E_DFILTER_TE_KEY "display_filter_te"
84
85 /* About Ethereal window */
86 void
87 about_ethereal( GtkWidget *w, gpointer data ) {
88   simple_dialog(ESD_TYPE_INFO, NULL,
89                 "GNU Ethereal - network protocol analyzer\n"
90                 "Version %s (C) 1998 Gerald Combs <gerald@zing.org>\n\n"
91                 "Contributors:\n"
92                 "Gilbert Ramirez Jr. <gram@verdict.uthscsa.edu>\n"
93                 "Hannes R. Boehm     <hannes@boehm.org>\n"
94                 "Mike Hall           <mlh@io.com>\n"
95                 "Bobo Rajec          <bobo@bsp-consulting.sk>\n"
96                 "Laurent Deniel      <deniel@worldnet.fr>\n"
97                 "Don Lafontaine      <lafont02@cn.ca>\n"
98                 "Guy Harris          <guy@netapp.com>\n"
99                 "Simon Wilkinson     <sxw@dcs.ed.ac.uk>\n\n"
100                 "See http://ethereal.zing.org for more information", VERSION);
101 }
102
103 /* Things to do when the OK button is pressed */
104 void
105 file_sel_ok_cb(GtkWidget *w, GtkFileSelection *fs) {
106   gchar     *cf_name;
107   int        err;
108   GtkWidget *filter_te = gtk_object_get_data(GTK_OBJECT(w), E_DFILTER_TE_KEY);
109
110   cf_name = g_strdup(gtk_file_selection_get_filename(GTK_FILE_SELECTION (fs)));
111   gtk_widget_hide(GTK_WIDGET (fs));
112   gtk_widget_destroy(GTK_WIDGET (fs));
113
114   if (cf.dfilter) g_free(cf.dfilter);
115   cf.dfilter = g_strdup(gtk_entry_get_text(GTK_ENTRY(filter_te)));
116   if ((err = load_cap_file(cf_name, &cf)) == 0)
117     chdir(cf_name);
118   g_free(cf_name);
119 }
120
121 /* Update the progress bar */
122 gint
123 file_progress_cb(gpointer p) {
124   gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar),
125     (gfloat) ftell(cf.fh) / (gfloat) cf.f_len);
126   return TRUE;
127 }
128
129 /* Follow a TCP stream */
130 void
131 follow_stream_cb( GtkWidget *w, gpointer data ) {
132   char filename1[128];
133   GtkWidget *streamwindow, *box, *text, *vscrollbar, *table;
134   GtkWidget *filter_te = gtk_object_get_data(GTK_OBJECT(w),
135     E_DFILTER_TE_KEY);
136   if( pi.ipproto == 6 ) {
137     /* we got tcp so we can follow */
138     /* check to see if we are using a filter */
139     if( cf.dfilter != NULL ) {
140       /* get rid of this one */
141       g_free( cf.dfilter );
142       cf.dfilter = NULL;
143     }
144     /* create a new one and set the display filter entry accordingly */
145     cf.dfilter = build_follow_filter( &pi );
146     gtk_entry_set_text(GTK_ENTRY(filter_te), cf.dfilter);
147     /* reload so it goes in effect. Also we set data_out_file which 
148        tells the tcp code to output the data */
149     close_cap_file( &cf, info_bar, file_ctx);
150     strcpy( filename1, tmpnam(NULL) );
151     data_out_file = fopen( filename1, "a" );
152     if( data_out_file == NULL ) {
153       fprintf( stderr, "Could not open tmp file %s\n", filename1 );
154     }
155     reset_tcp_reassembly();
156     load_cap_file( cf.filename, &cf );
157     /* the data_out_file should now be full of the streams information */
158     fclose( data_out_file );
159     /* the filename1 file now has all the text that was in the session */
160     streamwindow = gtk_window_new( GTK_WINDOW_TOPLEVEL);
161     gtk_widget_set_name( streamwindow, "TCP stream window" );
162     gtk_signal_connect( GTK_OBJECT(streamwindow), "delete_event",
163                         NULL, "WM destroy" );
164     gtk_signal_connect( GTK_OBJECT(streamwindow), "destroy",
165                         NULL, "WM destroy" );
166     gtk_window_set_title( GTK_WINDOW(streamwindow), "Contents of TCP stream" );
167     gtk_widget_set_usize( GTK_WIDGET(streamwindow), DEF_WIDTH, DEF_HEIGHT );
168     gtk_container_border_width( GTK_CONTAINER(streamwindow), 2 );
169     /* setup the container */
170     box = gtk_vbox_new( FALSE, 0 );
171     gtk_container_add( GTK_CONTAINER(streamwindow), box );
172     gtk_widget_show( box );
173     /* set up the table we attach to */
174     table = gtk_table_new( 1, 2, FALSE );
175     gtk_table_set_col_spacing( GTK_TABLE(table), 0, 2);
176     gtk_box_pack_start( GTK_BOX(box), table, TRUE, TRUE, 0 );
177     gtk_widget_show( table );
178     /* create a text box */
179     text = gtk_text_new( NULL, NULL );
180     gtk_text_set_editable( GTK_TEXT(text), FALSE);
181     gtk_table_attach( GTK_TABLE(table), text, 0, 1, 0, 1,
182                       GTK_EXPAND | GTK_SHRINK | GTK_FILL,
183                       GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0 );
184     gtk_widget_show(text);
185     /* create the scrollbar */
186     vscrollbar = gtk_vscrollbar_new( GTK_TEXT(text)->vadj );
187     gtk_table_attach( GTK_TABLE(table), vscrollbar, 1, 2, 0, 1,
188                       GTK_FILL, GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0 );
189     gtk_widget_show( vscrollbar );
190     gtk_widget_realize( text );
191     /* stop the updates while we fill the text box */
192     gtk_text_freeze( GTK_TEXT(text) );
193     data_out_file = NULL;
194     data_out_file = fopen( filename1, "r" );
195     if( data_out_file ) {
196       char buffer[1024];
197       int nchars;
198       while( 1 ) {
199         nchars = fread( buffer, 1, 1024, data_out_file );
200         gtk_text_insert( GTK_TEXT(text), m_r_font, NULL, NULL, buffer, nchars );
201         if( nchars < 1024 ) {
202           break;
203         }
204       }
205       fclose( data_out_file );
206       unlink( filename1 );
207     }
208     gtk_text_thaw( GTK_TEXT(text) );
209     data_out_file = NULL;
210     gtk_widget_show( streamwindow );
211     if( cf.dfilter != NULL ) {
212       g_free( cf.dfilter );
213       cf.dfilter = NULL;
214     }
215   } else {
216     simple_dialog(ESD_TYPE_WARN, NULL,
217       "Error following stream.  Please make\n"
218       "sure you have a TCP packet selected.");
219   }
220 }
221
222 /* Open a file */
223 void
224 file_open_cmd_cb(GtkWidget *w, gpointer data) {
225   file_sel = gtk_file_selection_new ("Ethereal: Open Capture File");
226   
227   /* Connect the ok_button to file_ok_sel_cb function and pass along the
228      pointer to the filter entry */
229   gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (file_sel)->ok_button),
230     "clicked", (GtkSignalFunc) file_sel_ok_cb, file_sel );
231   gtk_object_set_data(GTK_OBJECT(GTK_FILE_SELECTION(file_sel)->ok_button),
232     E_DFILTER_TE_KEY, gtk_object_get_data(GTK_OBJECT(w), E_DFILTER_TE_KEY));
233
234   /* Connect the cancel_button to destroy the widget */
235   gtk_signal_connect_object(GTK_OBJECT (GTK_FILE_SELECTION
236     (file_sel)->cancel_button), "clicked", (GtkSignalFunc)
237     gtk_widget_destroy, GTK_OBJECT (file_sel));
238
239   gtk_file_selection_set_filename(GTK_FILE_SELECTION(file_sel), "");
240
241   gtk_widget_show(file_sel);
242 }
243
244 /* Close a file */
245 void
246 file_close_cmd_cb(GtkWidget *widget, gpointer data) {
247   close_cap_file(&cf, info_bar, file_ctx);
248   set_menu_sensitivity("<Main>/File/Close", FALSE);
249   set_menu_sensitivity("<Main>/File/Reload", FALSE);
250 }
251
252 /* Reload a file using the current display filter */
253 void
254 file_reload_cmd_cb(GtkWidget *w, gpointer data) {
255   GtkWidget *filter_te = gtk_object_get_data(GTK_OBJECT(w), E_DFILTER_TE_KEY);
256
257   if (cf.dfilter) g_free(cf.dfilter);
258   cf.dfilter = g_strdup(gtk_entry_get_text(GTK_ENTRY(filter_te)));
259   load_cap_file(cf.filename, &cf);
260 }
261
262 /* Print a packet */
263 void
264 file_print_cmd_cb(GtkWidget *widget, gpointer data) {
265     print_tree(cf.pd, fd, GTK_TREE(tree_view));
266 }
267
268 /* What to do when a list item is selected/unselected */
269 void
270 packet_list_select_cb(GtkWidget *w, gint row, gint col, gpointer evt) {
271   GList      *l;
272
273   if (cf.pfh) return;  
274   blank_packetinfo();
275   gtk_text_freeze(GTK_TEXT(byte_view));
276   gtk_text_set_point(GTK_TEXT(byte_view), 0);
277   gtk_text_forward_delete(GTK_TEXT(byte_view),
278     gtk_text_get_length(GTK_TEXT(byte_view)));
279   l = g_list_nth(cf.plist, row);
280   if (l) {
281     fd = (frame_data *) l->data;
282     fseek(cf.fh, fd->file_off, SEEK_SET);
283     fread(cf.pd, sizeof(guint8), fd->cap_len, cf.fh);
284     dissect_packet(cf.pd, 0, 0, fd, GTK_TREE(tree_view));
285     packet_hex_print(GTK_TEXT(byte_view), cf.pd, fd->cap_len, -1, -1);
286   }
287   gtk_text_thaw(GTK_TEXT(byte_view));
288 }
289
290 void
291 packet_list_unselect_cb(GtkWidget *w, gint row, gint col, gpointer evt) {
292   gtk_text_freeze(GTK_TEXT(byte_view));
293   gtk_text_set_point(GTK_TEXT(byte_view), 0);
294   gtk_text_forward_delete(GTK_TEXT(byte_view),
295     gtk_text_get_length(GTK_TEXT(byte_view)));
296   gtk_text_thaw(GTK_TEXT(byte_view));
297   gtk_tree_clear_items(GTK_TREE(tree_view), 0,
298     g_list_length(GTK_TREE(tree_view)->children));
299 }
300
301 void
302 tree_view_cb(GtkWidget *w) {
303   gint       start = -1, len = -1;
304
305   if (GTK_TREE(w)->selection) {
306     start = (gint) gtk_object_get_data(GTK_OBJECT(GTK_TREE(w)->selection->data),
307       E_TREEINFO_START_KEY);
308     len   = (gint) gtk_object_get_data(GTK_OBJECT(GTK_TREE(w)->selection->data),
309       E_TREEINFO_LEN_KEY);
310   }
311
312   gtk_text_freeze(GTK_TEXT(byte_view));
313   gtk_text_set_point(GTK_TEXT(byte_view), 0);
314   gtk_text_forward_delete(GTK_TEXT(byte_view),
315     gtk_text_get_length(GTK_TEXT(byte_view)));
316   packet_hex_print(GTK_TEXT(byte_view), cf.pd, fd->cap_len, start, len);
317   gtk_text_thaw(GTK_TEXT(byte_view));
318 }
319
320 void
321 file_quit_cmd_cb (GtkWidget *widget, gpointer data) {
322   gtk_exit(0);
323 }
324
325 void blank_packetinfo() {
326   pi.srcip    = 0;
327   pi.destip   = 0;
328   pi.ipproto  = 0;
329   pi.srcport  = 0;
330   pi.destport = 0;
331 }
332
333 /* Things to do when the OK button is pressed */
334 void
335 main_realize_cb(GtkWidget *w, gpointer data) {
336   gchar  *cf_name = (gchar *) data;
337   int     err;
338   
339   if (cf_name) {
340     err = load_cap_file(cf_name, &cf);
341     cf_name[0] = '\0';
342   }
343   if (start_capture) {
344     if (cf.save_file)
345       capture(1);
346     else
347       capture(0);
348     start_capture = 0;
349   }
350 }
351
352 void 
353 print_usage(void) {
354
355   fprintf(stderr, "This is GNU %s %s\n", PACKAGE, VERSION);
356   fprintf(stderr, "%s [-v] [-b bold font] [-B byte view height] [-c count] [-h]\n",
357           PACKAGE);
358   fprintf(stderr, "         [-i interface] [-m medium font] [-n] [-P packet list height]\n");
359   fprintf(stderr, "         [-r infile] [-s snaplen] [-t <time stamp format>]\n");
360   fprintf(stderr, "         [-T tree view height] [-w savefile] \n");
361 }
362
363 int
364 main(int argc, char *argv[])
365 {
366   int                  opt;
367   extern char         *optarg;
368   GtkWidget           *window, *main_vbox, *menubar, *u_pane, *l_pane,
369                       *bv_table, *bv_hscroll, *bv_vscroll, *stat_hbox, 
370                       *tv_scrollw, *filter_bt, *filter_te;
371   GtkStyle            *pl_style;
372   GtkAcceleratorTable *accel;
373   gint                 col_width, pl_size = 280, tv_size = 95, bv_size = 75;
374   gchar               *rc_file, *cf_name = NULL;
375   gchar               *cl_title[] = {"No.", "Time", "Source", "Destination",
376                       "Protocol", "Info"};
377   gchar               *medium_font = MONO_MEDIUM_FONT;
378   gchar               *bold_font = MONO_BOLD_FONT;
379
380   /* Initialize the capture file struct */
381   cf.plist     = NULL;
382   cf.pfh       = NULL;
383   cf.fh        = NULL;
384   cf.dfilter   = NULL;
385   cf.cfilter   = NULL;
386   cf.iface     = NULL;
387   cf.save_file = NULL;
388   cf.snap      = 68;
389   cf.count     = 0;
390     
391   /* Let GTK get its args */
392   gtk_init (&argc, &argv);
393
394   /* Now get our args */
395   while ((opt = getopt(argc, argv, "b:B:c:hi:m:nP:r:s:t:T:w:v")) != EOF) {
396     switch (opt) {
397       case 'b':        /* Bold font */
398         bold_font = g_strdup(optarg);
399         break;
400       case 'B':        /* Byte view pane height */
401         bv_size = atoi(optarg);
402         break;
403       case 'c':        /* Capture xxx packets */
404         cf.count = atoi(optarg);
405         break;
406       case 'h':        /* Print help and exit */
407         print_usage();
408         exit(0);
409         break;
410       case 'i':        /* Use interface xxx */
411         cf.iface = g_strdup(optarg);
412         break;
413       case 'm':        /* Medium font */
414         medium_font = g_strdup(optarg);
415         break;
416       case 'n':        /* No name resolution */
417         g_resolving_actif = 0;
418         break;
419       case 'k':        /* Start capture immediately */
420         start_capture = 1;
421         break;
422       case 'P':        /* Packet list pane height */
423         pl_size = atoi(optarg);
424         break;
425       case 'r':        /* Read capture file xxx */
426         cf_name = g_strdup(optarg);
427         break;
428       case 's':        /* Set the snapshot (capture) length */
429         cf.snap = atoi(optarg);
430         break;
431       case 't':        /* Time stamp type */
432         if (strcmp(optarg, "r") == 0)
433           timestamp_type = RELATIVE;
434         else if (strcmp(optarg, "a") == 0)
435           timestamp_type = ABSOLUTE;
436         else if (strcmp(optarg, "d") == 0)
437           timestamp_type = DELTA;
438         else {
439           fprintf(stderr, "ethereal: Invalid time stamp type \"%s\"\n",
440             optarg);
441           fprintf(stderr, "It must be \"r\" for relative, \"a\" for absolute,\n");
442           fprintf(stderr, "or \"d\" for delta.\n");
443           exit(1);
444         }
445         break;
446       case 'T':        /* Tree view pane height */
447         tv_size = atoi(optarg);
448         break;
449       case 'v':        /* Show version and exit */
450         printf("%s %s\n", PACKAGE, VERSION);
451         exit(0);
452         break;
453       case 'w':        /* Write capture file xxx */
454         cf.save_file = g_strdup(optarg);
455         break;
456     }
457   }
458   
459   if (cf.snap < 1)
460     cf.snap = 4096;
461   else if (cf.snap < 68)
462     cf.snap = 68;
463   
464   rc_file = (gchar *) g_malloc(strlen(getenv("HOME")) + strlen(RC_FILE) + 4);
465   sprintf(rc_file, "%s/%s", getenv("HOME"), RC_FILE);
466   gtk_rc_parse(rc_file);
467
468   /* initialize printer options. temporary! we should only initialize
469    * if the options are not set in some ethereal initialization file */
470   printer_opts.output_format = 0;
471   printer_opts.output_dest = 0;
472   printer_opts.file = g_strdup("ethereal.out");
473   printer_opts.cmd = g_strdup("lpr");
474
475   if ((m_r_font = gdk_font_load(medium_font)) == NULL) {
476     fprintf(stderr, "Error font %s not found (use -m option)\n", medium_font);
477     exit(1);
478   }
479
480   if ((m_b_font = gdk_font_load(bold_font)) == NULL) {
481     fprintf(stderr, "Error font %s not found (use -b option)\n", bold_font);
482     exit(1);
483   }
484
485   /* Main window */  
486   window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
487   gtk_widget_set_name(window, "main window");
488   gtk_signal_connect(GTK_OBJECT(window), "delete_event",
489     GTK_SIGNAL_FUNC(file_quit_cmd_cb), "WM destroy");
490   gtk_signal_connect(GTK_OBJECT(window), "destroy", 
491     GTK_SIGNAL_FUNC(file_quit_cmd_cb), "WM destroy");
492   gtk_signal_connect(GTK_OBJECT (window), "realize",
493     GTK_SIGNAL_FUNC(main_realize_cb), cf_name);
494   gtk_window_set_title(GTK_WINDOW(window), "The Ethereal Network Analyzer");
495   gtk_widget_set_usize(GTK_WIDGET(window), DEF_WIDTH, -1);
496
497   /* Container for menu bar, paned windows and progress/info box */
498   main_vbox = gtk_vbox_new(FALSE, 1);
499   gtk_container_border_width(GTK_CONTAINER(main_vbox), 1);
500   gtk_container_add(GTK_CONTAINER(window), main_vbox);
501   gtk_widget_show(main_vbox);
502
503   /* Menu bar */
504   get_main_menu(&menubar, &accel);
505   gtk_window_add_accelerator_table(GTK_WINDOW(window), accel);
506   gtk_box_pack_start(GTK_BOX(main_vbox), menubar, FALSE, TRUE, 0);
507   gtk_widget_show(menubar);
508
509   /* Panes for the packet list, tree, and byte view */
510   u_pane = gtk_vpaned_new();
511   gtk_paned_gutter_size(GTK_PANED(u_pane), (GTK_PANED(u_pane))->handle_size);
512   l_pane = gtk_vpaned_new();
513   gtk_paned_gutter_size(GTK_PANED(l_pane), (GTK_PANED(l_pane))->handle_size);
514   gtk_container_add(GTK_CONTAINER(main_vbox), u_pane);
515   gtk_widget_show(u_pane);
516   gtk_paned_add2 (GTK_PANED(u_pane), l_pane);
517   gtk_widget_show(l_pane);
518
519   /* Packet list */
520   packet_list = gtk_clist_new_with_titles(NUM_COLS, cl_title);
521   pl_style = gtk_style_new();
522   gdk_font_unref(pl_style->font);
523   pl_style->font = m_r_font;
524   gtk_widget_set_style(packet_list, pl_style);
525   gtk_widget_set_name(packet_list, "packet list");
526   gtk_signal_connect(GTK_OBJECT(packet_list), "select_row",
527     GTK_SIGNAL_FUNC(packet_list_select_cb), NULL);
528   gtk_signal_connect(GTK_OBJECT(packet_list), "unselect_row",
529     GTK_SIGNAL_FUNC(packet_list_unselect_cb), NULL);
530   gtk_clist_set_column_justification(GTK_CLIST(packet_list), 0, 
531     GTK_JUSTIFY_RIGHT);
532   col_width = (gdk_string_width(pl_style->font, "0") * 7) + 2;
533   gtk_clist_set_column_width(GTK_CLIST(packet_list), COL_NUM, col_width);
534   if (timestamp_type == ABSOLUTE)
535     col_width = gdk_string_width(pl_style->font, "00:00:00.000000");
536   else
537     col_width = gdk_string_width(pl_style->font, "0000.000000");
538   gtk_clist_set_column_width(GTK_CLIST(packet_list), COL_TIME, col_width);
539   col_width = gdk_string_width(pl_style->font, "00:00:00:00:00:00") + 2;
540   gtk_clist_set_column_width(GTK_CLIST(packet_list), COL_SOURCE, col_width);
541   gtk_clist_set_column_width(GTK_CLIST(packet_list), COL_DESTINATION, col_width);
542   col_width = gdk_string_width(pl_style->font, "NBNS (UDP)") + 2;
543   gtk_clist_set_column_width(GTK_CLIST(packet_list), COL_PROTOCOL, col_width);
544   gtk_widget_set_usize(packet_list, -1, pl_size);
545   gtk_paned_add1(GTK_PANED(u_pane), packet_list);
546   gtk_widget_show(packet_list);
547   
548   /* Tree view */
549   tv_scrollw = gtk_scrolled_window_new(NULL, NULL);
550   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW(tv_scrollw),
551     GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
552   gtk_paned_add1(GTK_PANED(l_pane), tv_scrollw);
553   gtk_widget_set_usize(tv_scrollw, -1, tv_size);
554   gtk_widget_show(tv_scrollw);
555   
556   tree_view = gtk_tree_new();
557   gtk_container_add(GTK_CONTAINER(tv_scrollw), tree_view);
558   gtk_tree_set_selection_mode(GTK_TREE(tree_view), GTK_SELECTION_SINGLE);
559   gtk_tree_set_view_lines(GTK_TREE(tree_view), FALSE);
560   gtk_tree_set_view_mode(GTK_TREE(tree_view), TRUE);
561   gtk_signal_connect(GTK_OBJECT(tree_view), "selection_changed",
562     GTK_SIGNAL_FUNC(tree_view_cb), NULL);
563   gtk_widget_show(tree_view);
564
565   /* Byte view */
566   bv_table = gtk_table_new (2, 2, FALSE);
567   gtk_paned_add2(GTK_PANED(l_pane), bv_table);
568   gtk_widget_set_usize(bv_table, -1, bv_size);
569   gtk_widget_show(bv_table);
570
571   byte_view = gtk_text_new(NULL, NULL);
572   gtk_text_set_editable(GTK_TEXT(byte_view), FALSE);
573   gtk_text_set_word_wrap(GTK_TEXT(byte_view), FALSE);
574   gtk_table_attach (GTK_TABLE (bv_table), byte_view, 0, 1, 0, 1,
575     GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 0);
576   gtk_widget_show(byte_view);
577
578   bv_hscroll = gtk_hscrollbar_new(GTK_TEXT(byte_view)->hadj);
579   gtk_table_attach(GTK_TABLE(bv_table), bv_hscroll, 0, 1, 1, 2,
580     GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0);
581   gtk_widget_show (bv_hscroll);
582
583   bv_vscroll = gtk_vscrollbar_new(GTK_TEXT(byte_view)->vadj);
584   gtk_table_attach(GTK_TABLE(bv_table), bv_vscroll, 1, 2, 0, 1,
585     GTK_FILL, GTK_EXPAND | GTK_FILL | GTK_SHRINK, 0, 0);
586   gtk_widget_show(bv_vscroll);
587   
588   /* Progress/filter/info box */
589   stat_hbox = gtk_hbox_new(FALSE, 1);
590   gtk_container_border_width(GTK_CONTAINER(stat_hbox), 0);
591   gtk_box_pack_start(GTK_BOX(main_vbox), stat_hbox, FALSE, TRUE, 0);
592   gtk_widget_show(stat_hbox);
593
594   prog_bar = gtk_progress_bar_new();  
595   gtk_box_pack_start(GTK_BOX(stat_hbox), prog_bar, FALSE, TRUE, 3);
596   gtk_widget_show(prog_bar);
597
598   filter_bt = gtk_button_new_with_label("Filter:");
599   gtk_signal_connect(GTK_OBJECT(filter_bt), "clicked",
600     GTK_SIGNAL_FUNC(prefs_cb), (gpointer) E_PR_PG_FILTER);
601   gtk_box_pack_start(GTK_BOX(stat_hbox), filter_bt, FALSE, TRUE, 0);
602   gtk_widget_show(filter_bt);
603   
604   filter_te = gtk_entry_new();
605   gtk_object_set_data(GTK_OBJECT(filter_bt), E_FILT_TE_PTR_KEY, filter_te);
606   gtk_box_pack_start(GTK_BOX(stat_hbox), filter_te, TRUE, TRUE, 3);
607   gtk_widget_show(filter_te);
608   set_menu_object_data("<Main>/File/Open", E_DFILTER_TE_KEY, filter_te);
609   set_menu_object_data("<Main>/File/Reload", E_DFILTER_TE_KEY, filter_te);
610   set_menu_object_data("<Main>/Tools/Follow TCP Stream", E_DFILTER_TE_KEY,
611     filter_te);
612
613   info_bar = gtk_statusbar_new();
614   main_ctx = gtk_statusbar_get_context_id(GTK_STATUSBAR(info_bar), "main");
615   file_ctx = gtk_statusbar_get_context_id(GTK_STATUSBAR(info_bar), "file");
616   gtk_statusbar_push(GTK_STATUSBAR(info_bar), main_ctx, DEF_READY_MESSAGE);
617   gtk_box_pack_start(GTK_BOX(stat_hbox), info_bar, TRUE, TRUE, 0);
618   gtk_widget_show(info_bar);
619
620   gtk_widget_show(window);
621   gtk_main();
622
623   exit(0);
624 }