3 * $Id: main.c,v 1.7 1999/09/23 06:27:27 guy Exp $
5 * Ethereal - Network traffic analyzer
6 * By Gerald Combs <gerald@zing.org>
7 * Copyright 1998 Gerald Combs
9 * Richard Sharpe, 13-Feb-1999, added support for initializing structures
10 * needed by dissect routines
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
30 * - Check for end of packet in dissect_* routines.
32 * - Multiple window support
33 * - Add cut/copy/paste
34 * - Create header parsing routines
35 * - Make byte view scrollbars automatic?
36 * - Make byte view selections more fancy?
55 #include <sys/types.h>
63 #ifdef HAVE_NETINET_IN_H
64 #include <netinet/in.h>
69 #ifdef NEED_SNPRINTF_H
75 # include "snprintf.h"
78 #ifdef NEED_STRERROR_H
83 #include "timestamp.h"
89 #include "prefs_dlg.h"
95 #include "proto_draw.h"
99 FILE *data_out_file = NULL;
102 GtkWidget *file_sel, *packet_list, *tree_view, *byte_view, *prog_bar,
104 GdkFont *m_r_font, *m_b_font;
105 guint main_ctx, file_ctx;
106 gint start_capture = 0;
107 gchar comp_info_str[256];
108 gchar *ethereal_path = NULL;
109 gchar *medium_font = MONO_MEDIUM_FONT;
110 gchar *bold_font = MONO_BOLD_FONT;
111 gchar *last_open_dir = NULL;
113 ts_type timestamp_type = RELATIVE;
115 GtkStyle *item_style;
118 int sync_mode; /* allow sync */
119 int sync_pipe[2]; /* used to sync father */
120 int fork_mode; /* fork a child to do the capture */
121 int quit_after_cap; /* Makes a "capture only mode". Implies -k */
124 /* Specifies byte offsets for object selected in tree */
125 static gint tree_selected_start=-1, tree_selected_len=-1;
128 /* About Ethereal window */
130 about_ethereal( GtkWidget *w, gpointer data ) {
131 simple_dialog(ESD_TYPE_INFO, NULL,
132 "GNU Ethereal - network protocol analyzer\n"
133 "Version %s (C) 1998 Gerald Combs <gerald@zing.org>\n"
134 "Compiled with %s\n\n"
137 "Gilbert Ramirez <gramirez@tivoli.com>\n"
138 "Hannes R. Boehm <hannes@boehm.org>\n"
139 "Mike Hall <mlh@io.com>\n"
140 "Bobo Rajec <bobo@bsp-consulting.sk>\n"
141 "Laurent Deniel <deniel@worldnet.fr>\n"
142 "Don Lafontaine <lafont02@cn.ca>\n"
143 "Guy Harris <guy@netapp.com>\n"
144 "Simon Wilkinson <sxw@dcs.ed.ac.uk>\n"
145 "Joerg Mayer <jmayer@telemation.de>\n"
146 "Martin Maciaszek <fastjack@i-s-o.net>\n"
147 "Didier Jorand <Didier.Jorand@alcatel.fr>\n"
148 "Jun-ichiro itojun Hagino <itojun@iijlab.net>\n"
149 "Richard Sharpe <sharpe@ns.aus.com>\n"
150 "John McDermott <jjm@jkintl.com>\n"
151 "Jeff Jahr <jjahr@shastanets.com>\n"
152 "Brad Robel-Forrest <bradr@watchguard.com>\n"
153 "Ashok Narayanan <ashokn@cisco.com>\n"
154 "Aaron Hillegass <aaron@classmax.com>\n"
155 "Jason Lango <jal@netapp.com>\n"
156 "Johan Feyaerts <Johan.Feyaerts@siemens.atea.be>\n"
157 "Olivier Abad <abad@daba.dhis.org>\n"
158 "Thierry Andry <Thierry.Andry@advalvas.be>\n"
159 "Jeff Foster <jfoste@woodward.com>\n"
160 "Peter Torvals <petertv@xoommail.com>\n"
162 "\nSee http://ethereal.zing.org for more information",
163 VERSION, comp_info_str);
166 /* Follow the TCP stream, if any, to which the last packet that we called
167 a dissection routine on belongs (this might be the most recently
168 selected packet, or it might be the last packet in the file). */
170 follow_stream_cb( GtkWidget *w, gpointer data ) {
171 char filename1[128+1];
172 GtkWidget *streamwindow, *box, *text, *vscrollbar, *table;
175 if( pi.ipproto == 6 ) {
176 /* we got tcp so we can follow */
177 /* Create a temporary file into which to dump the reassembled data
178 from the TCP stream, and set "data_out_file" to refer to it, so
179 that the TCP code will write to it.
181 XXX - it might be nicer to just have the TCP code directly
182 append stuff to the text widget for the TCP stream window,
183 if we can arrange that said window not pop up until we're
185 tmp_fd = create_tempfile( filename1, sizeof filename1, "follow");
187 simple_dialog(ESD_TYPE_WARN, NULL,
188 "Could not create temporary file %s: %s", filename1, strerror(errno));
191 data_out_file = fdopen( tmp_fd, "w" );
192 if( data_out_file == NULL ) {
193 simple_dialog(ESD_TYPE_WARN, NULL,
194 "Could not create temporary file %s: %s", filename1, strerror(errno));
200 /* Create a new filter that matches all packets in the TCP stream,
201 and set the display filter entry accordingly */
202 reset_tcp_reassembly();
203 cf.dfilter = build_follow_filter( &pi );
205 /* Run the display filter so it goes in effect. */
208 /* the data_out_file should now be full of the streams information */
209 fclose( data_out_file );
211 /* the filename1 file now has all the text that was in the session */
212 streamwindow = gtk_window_new( GTK_WINDOW_TOPLEVEL);
213 gtk_widget_set_name( streamwindow, "TCP stream window" );
214 gtk_signal_connect( GTK_OBJECT(streamwindow), "delete_event",
215 NULL, "WM destroy" );
216 gtk_signal_connect( GTK_OBJECT(streamwindow), "destroy",
217 NULL, "WM destroy" );
218 if( incomplete_tcp_stream ) {
219 gtk_window_set_title( GTK_WINDOW(streamwindow),
220 "Contents of TCP stream (incomplete)" );
222 gtk_window_set_title( GTK_WINDOW(streamwindow),
223 "Contents of TCP stream" );
225 gtk_widget_set_usize( GTK_WIDGET(streamwindow), DEF_WIDTH, DEF_HEIGHT );
226 gtk_container_border_width( GTK_CONTAINER(streamwindow), 2 );
228 /* setup the container */
229 box = gtk_vbox_new( FALSE, 0 );
230 gtk_container_add( GTK_CONTAINER(streamwindow), box );
231 gtk_widget_show( box );
233 /* set up the table we attach to */
234 table = gtk_table_new( 1, 2, FALSE );
235 gtk_table_set_col_spacing( GTK_TABLE(table), 0, 2);
236 gtk_box_pack_start( GTK_BOX(box), table, TRUE, TRUE, 0 );
237 gtk_widget_show( table );
239 /* create a text box */
240 text = gtk_text_new( NULL, NULL );
241 gtk_text_set_editable( GTK_TEXT(text), FALSE);
242 gtk_table_attach( GTK_TABLE(table), text, 0, 1, 0, 1,
243 GTK_EXPAND | GTK_SHRINK | GTK_FILL,
244 GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0 );
245 gtk_widget_show(text);
247 /* create the scrollbar */
248 vscrollbar = gtk_vscrollbar_new( GTK_TEXT(text)->vadj );
249 gtk_table_attach( GTK_TABLE(table), vscrollbar, 1, 2, 0, 1,
250 GTK_FILL, GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0 );
251 gtk_widget_show( vscrollbar );
252 gtk_widget_realize( text );
254 /* stop the updates while we fill the text box */
255 gtk_text_freeze( GTK_TEXT(text) );
256 data_out_file = fopen( filename1, "r" );
257 if( data_out_file ) {
261 nchars = fread( buffer, 1, 1024, data_out_file );
262 gtk_text_insert( GTK_TEXT(text), m_r_font, NULL, NULL, buffer, nchars );
263 if( nchars < 1024 ) {
267 if( ferror( data_out_file ) ) {
268 simple_dialog(ESD_TYPE_WARN, NULL,
269 "Error reading temporary file %s: %s", filename1, strerror(errno));
271 fclose( data_out_file );
273 simple_dialog(ESD_TYPE_WARN, NULL,
274 "Could not open temporary file %s: %s", filename1, strerror(errno));
276 gtk_text_thaw( GTK_TEXT(text) );
278 data_out_file = NULL;
279 gtk_widget_show( streamwindow );
281 simple_dialog(ESD_TYPE_WARN, NULL,
282 "Error following stream. Please make\n"
283 "sure you have a TCP packet selected.");
287 /* Match selected byte pattern */
289 match_selected_cb(GtkWidget *w, gpointer data)
291 char *buf = g_malloc(1024);
292 GtkWidget *filter_te = NULL;
297 filter_te = gtk_object_get_data(GTK_OBJECT(w), E_DFILTER_TE_KEY);
299 if (tree_selected_start<0) {
300 simple_dialog(ESD_TYPE_WARN, NULL,
301 "Error determining selected bytes. Please make\n"
302 "sure you have selected a field within the tree\n"
303 "view to be matched.");
307 c = cf.pd + tree_selected_start;
310 sprintf(ptr, "frame[%d : %d] == ", tree_selected_start, tree_selected_len);
311 ptr = buf+strlen(buf);
313 if (tree_selected_len == 1) {
314 sprintf(ptr, "0x%02x", *c++);
317 for (i=0;i<tree_selected_len; i++) {
319 sprintf(ptr, "%02x", *c++);
322 sprintf(ptr, ":%02x", *c++);
324 ptr = buf+strlen(buf);
328 if( cf.dfilter != NULL ) {
329 /* get rid of this one */
330 g_free( cf.dfilter );
332 /* create a new one and set the display filter entry accordingly */
335 gtk_entry_set_text(GTK_ENTRY(filter_te), cf.dfilter);
337 /* Run the display filter so it goes in effect. */
341 /* Run the current display filter on the current packet set, and
344 filter_activate_cb(GtkWidget *w, gpointer data)
346 char *s = gtk_entry_get_text(GTK_ENTRY(w));
351 /* simple check for empty string. XXX - need to modify to search for /^\s+$/ */
356 cf.dfilter = g_strdup(s);
362 /* What to do when a list item is selected/unselected */
364 packet_list_select_cb(GtkWidget *w, gint row, gint col, gpointer evt) {
375 select_packet(&cf, row);
379 packet_list_unselect_cb(GtkWidget *w, gint row, gint col, gpointer evt) {
380 unselect_packet(&cf);
384 tree_view_cb(GtkWidget *w, gpointer data) {
386 tree_selected_start = -1;
387 tree_selected_len = -1;
389 if (GTK_TREE(w)->selection) {
390 tree_selected_start =
391 (gint) gtk_object_get_data(GTK_OBJECT(GTK_TREE(w)->selection->data),
392 E_TREEINFO_START_KEY);
394 (gint) gtk_object_get_data(GTK_OBJECT(GTK_TREE(w)->selection->data),
398 gtk_text_freeze(GTK_TEXT(byte_view));
399 gtk_text_set_point(GTK_TEXT(byte_view), 0);
400 gtk_text_forward_delete(GTK_TEXT(byte_view),
401 gtk_text_get_length(GTK_TEXT(byte_view)));
402 packet_hex_print(GTK_TEXT(byte_view), cf.pd, cf.fd->cap_len,
406 gtk_text_thaw(GTK_TEXT(byte_view));
409 void collapse_all_cb(GtkWidget *widget, gpointer data) {
410 if (cf.protocol_tree)
411 collapse_all_tree(cf.protocol_tree, tree_view);
414 void expand_all_cb(GtkWidget *widget, gpointer data) {
415 if (cf.protocol_tree)
416 expand_all_tree(cf.protocol_tree, tree_view);
420 file_quit_cmd_cb (GtkWidget *widget, gpointer data) {
421 if (cf.save_file && !cf.user_saved) {
422 unlink(cf.save_file);
427 void blank_packetinfo() {
435 /* Things to do when the main window is realized */
437 main_realize_cb(GtkWidget *w, gpointer data) {
446 /* call initialization routines at program startup time */
448 ethereal_proto_init(void) {
455 ethereal_proto_cleanup(void) {
463 fprintf(stderr, "This is GNU %s %s, compiled with %s\n", PACKAGE,
464 VERSION, comp_info_str);
465 fprintf(stderr, "%s [-vh] [-FkQS] [-b bold font] [-B byte view height] [-c count]\n",
467 fprintf(stderr, " [-f \"filter expression\"] [-i interface] [-m medium font] [-n]\n");
468 fprintf(stderr, " [-P packet list height] [-r infile] [-s snaplen]\n");
469 fprintf(stderr, " [-t <time stamp format>] [-T tree view height] [-w savefile] \n");
472 /* And now our feature presentation... [ fade to music ] */
474 main(int argc, char *argv[])
476 char *command_name, *s;
483 int pf_open_errno = 0;
485 GtkWidget *window, *main_vbox, *menubar, *u_pane, *l_pane,
486 *bv_table, *bv_hscroll, *bv_vscroll, *stat_hbox,
487 *tv_scrollw, *filter_bt, *filter_te;
489 GtkAccelGroup *accel;
490 GtkWidget *packet_sw;
491 gint pl_size = 280, tv_size = 95, bv_size = 75;
492 gchar *rc_file, *cf_name = NULL, *rfilter = NULL;
493 dfilter *rfcode = NULL;
494 gboolean rfilter_parse_failed = FALSE;
497 ethereal_path = argv[0];
499 /* If invoked as "ethereal-dump-fields", we dump out a glossary of
500 display filter symbols; we specify that by checking the name,
501 so that we can do so before looking at the argument list -
502 we don't want to look at the argument list, because we don't
503 want to call "gtk_init()", because we don't want to have to
504 do any X stuff just to do a build. */
505 command_name = strrchr(ethereal_path, '/');
506 if (command_name == NULL)
507 command_name = ethereal_path;
510 if (strcmp(command_name, "ethereal-dump-fields") == 0) {
511 ethereal_proto_init();
512 proto_registrar_dump();
516 /* Let GTK get its args */
517 gtk_init (&argc, &argv);
519 prefs = read_prefs(&pf_path);
520 if (pf_path != NULL) {
521 /* The preferences file exists, but couldn't be opened; "pf_path" is
522 its pathname. Remember "errno", as that says why the attempt
524 pf_open_errno = errno;
527 /* Initialize the capture file struct */
534 cf.dfcode = dfilter_new();
540 cf.save_file_fd = -1;
542 cf.snap = WTAP_MAX_PACKET_SIZE;
544 cf.cinfo.num_cols = prefs->num_cols;
545 cf.cinfo.col_fmt = (gint *) g_malloc(sizeof(gint) * cf.cinfo.num_cols);
546 cf.cinfo.fmt_matx = (gboolean **) g_malloc(sizeof(gboolean *) * cf.cinfo.num_cols);
547 cf.cinfo.col_width = (gint *) g_malloc(sizeof(gint) * cf.cinfo.num_cols);
548 cf.cinfo.col_title = (gchar **) g_malloc(sizeof(gchar *) * cf.cinfo.num_cols);
549 cf.cinfo.col_data = (gchar **) g_malloc(sizeof(gchar *) * cf.cinfo.num_cols);
551 /* Assemble the compile-time options */
552 snprintf(comp_info_str, 256,
553 #ifdef GTK_MAJOR_VERSION
554 "GTK+ %d.%d.%d, %s libpcap", GTK_MAJOR_VERSION, GTK_MINOR_VERSION,
557 "GTK+ (version unknown), %s libpcap",
568 /* Now get our args */
569 while ((opt = getopt(argc, argv, "b:B:c:f:Fhi:km:nP:Qr:R:Ss:t:T:w:W:v")) != EOF) {
571 case 'b': /* Bold font */
572 bold_font = g_strdup(optarg);
574 case 'B': /* Byte view pane height */
575 bv_size = atoi(optarg);
577 case 'c': /* Capture xxx packets */
578 cf.count = atoi(optarg);
582 cf.cfilter = g_strdup(optarg);
584 case 'F': /* Fork to capture */
588 case 'h': /* Print help and exit */
592 case 'i': /* Use interface xxx */
593 cf.iface = g_strdup(optarg);
595 case 'm': /* Medium font */
596 medium_font = g_strdup(optarg);
598 case 'n': /* No name resolution */
599 g_resolving_actif = 0;
602 case 'k': /* Start capture immediately */
606 case 'P': /* Packet list pane height */
607 pl_size = atoi(optarg);
610 case 'Q': /* Quit after capture (just capture to file) */
612 start_capture = 1; /*** -Q implies -k !! ***/
615 case 'r': /* Read capture file xxx */
616 cf_name = g_strdup(optarg);
618 case 'R': /* Read file filter */
622 case 's': /* Set the snapshot (capture) length */
623 cf.snap = atoi(optarg);
625 case 'S': /* "Sync" mode: used for following file ala tail -f */
627 fork_mode = 1; /* -S implies -F */
630 case 't': /* Time stamp type */
631 if (strcmp(optarg, "r") == 0)
632 timestamp_type = RELATIVE;
633 else if (strcmp(optarg, "a") == 0)
634 timestamp_type = ABSOLUTE;
635 else if (strcmp(optarg, "d") == 0)
636 timestamp_type = DELTA;
638 fprintf(stderr, "ethereal: Invalid time stamp type \"%s\"\n",
640 fprintf(stderr, "It must be \"r\" for relative, \"a\" for absolute,\n");
641 fprintf(stderr, "or \"d\" for delta.\n");
645 case 'T': /* Tree view pane height */
646 tv_size = atoi(optarg);
648 case 'v': /* Show version and exit */
649 printf("%s %s, with %s\n", PACKAGE, VERSION, comp_info_str);
653 case 'w': /* Write to capture file xxx */
654 cf.save_file = g_strdup(optarg);
656 case 'W': /* Write to capture file FD xxx */
657 cf.save_file_fd = atoi(optarg);
665 if (cf.iface == NULL) {
666 fprintf(stderr, "ethereal: \"-k\" flag was specified without \"-i\" flag\n");
669 if (cf.save_file == NULL) {
670 fprintf(stderr, "ethereal: \"-k\" flag was specified without \"-w\" flag\n");
675 if (cf.save_file_fd == -1) {
676 fprintf(stderr, "ethereal: \"-k\" flag was specified with \"-%c\" flag but without \"-W\" flag\n",
677 (sync_mode ? 'S' : 'F'));
684 /* Build the column format array */
685 for (i = 0; i < cf.cinfo.num_cols; i++) {
686 cf.cinfo.col_fmt[i] = get_column_format(i);
687 cf.cinfo.col_title[i] = g_strdup(get_column_title(i));
688 cf.cinfo.fmt_matx[i] = (gboolean *) g_malloc0(sizeof(gboolean) *
690 get_column_format_matches(cf.cinfo.fmt_matx[i], cf.cinfo.col_fmt[i]);
691 cf.cinfo.col_data[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_LEN);
695 cf.snap = WTAP_MAX_PACKET_SIZE;
696 else if (cf.snap < MIN_PACKET_SIZE)
697 cf.snap = MIN_PACKET_SIZE;
699 rc_file = (gchar *) g_malloc(strlen(getenv("HOME")) + strlen(RC_FILE) + 4);
700 sprintf(rc_file, "%s/%s", getenv("HOME"), RC_FILE);
701 gtk_rc_parse(rc_file);
703 if ((m_r_font = gdk_font_load(medium_font)) == NULL) {
704 fprintf(stderr, "ethereal: Error font %s not found (use -m option)\n", medium_font);
708 if ((m_b_font = gdk_font_load(bold_font)) == NULL) {
709 fprintf(stderr, "ethereal: Error font %s not found (use -b option)\n", bold_font);
714 window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
715 gtk_widget_set_name(window, "main window");
716 gtk_signal_connect(GTK_OBJECT(window), "delete_event",
717 GTK_SIGNAL_FUNC(file_quit_cmd_cb), "WM destroy");
718 gtk_signal_connect(GTK_OBJECT(window), "destroy",
719 GTK_SIGNAL_FUNC(file_quit_cmd_cb), "WM destroy");
720 gtk_signal_connect(GTK_OBJECT (window), "realize",
721 GTK_SIGNAL_FUNC(main_realize_cb), NULL);
722 gtk_window_set_title(GTK_WINDOW(window), "The Ethereal Network Analyzer");
723 gtk_widget_set_usize(GTK_WIDGET(window), DEF_WIDTH, -1);
724 gtk_window_set_policy(GTK_WINDOW(window), TRUE, TRUE, FALSE);
726 /* Container for menu bar, paned windows and progress/info box */
727 main_vbox = gtk_vbox_new(FALSE, 1);
728 gtk_container_border_width(GTK_CONTAINER(main_vbox), 1);
729 gtk_container_add(GTK_CONTAINER(window), main_vbox);
730 gtk_widget_show(main_vbox);
733 get_main_menu(&menubar, &accel);
734 gtk_window_add_accel_group(GTK_WINDOW(window), accel);
735 gtk_box_pack_start(GTK_BOX(main_vbox), menubar, FALSE, TRUE, 0);
736 gtk_widget_show(menubar);
738 /* Panes for the packet list, tree, and byte view */
739 u_pane = gtk_vpaned_new();
740 gtk_paned_gutter_size(GTK_PANED(u_pane), (GTK_PANED(u_pane))->handle_size);
741 l_pane = gtk_vpaned_new();
742 gtk_paned_gutter_size(GTK_PANED(l_pane), (GTK_PANED(l_pane))->handle_size);
743 gtk_container_add(GTK_CONTAINER(main_vbox), u_pane);
744 gtk_widget_show(u_pane);
745 gtk_paned_add2 (GTK_PANED(u_pane), l_pane);
746 gtk_widget_show(l_pane);
749 packet_list = gtk_clist_new_with_titles(cf.cinfo.num_cols, cf.cinfo.col_title);
750 gtk_clist_column_titles_passive(GTK_CLIST(packet_list));
751 packet_sw = gtk_scrolled_window_new(NULL, NULL);
752 gtk_widget_show(packet_sw);
753 gtk_container_add(GTK_CONTAINER(packet_sw), packet_list);
754 pl_style = gtk_style_new();
755 gdk_font_unref(pl_style->font);
756 pl_style->font = m_r_font;
757 gtk_widget_set_style(packet_list, pl_style);
758 gtk_widget_set_name(packet_list, "packet list");
759 gtk_signal_connect(GTK_OBJECT(packet_list), "select_row",
760 GTK_SIGNAL_FUNC(packet_list_select_cb), NULL);
761 gtk_signal_connect(GTK_OBJECT(packet_list), "unselect_row",
762 GTK_SIGNAL_FUNC(packet_list_unselect_cb), NULL);
763 for (i = 0; i < cf.cinfo.num_cols; i++) {
764 if (get_column_resize_type(cf.cinfo.col_fmt[i]) != RESIZE_MANUAL)
765 gtk_clist_set_column_auto_resize(GTK_CLIST(packet_list), i, TRUE);
767 /* Right-justify the packet number column. */
768 if (cf.cinfo.col_fmt[i] == COL_NUMBER)
769 gtk_clist_set_column_justification(GTK_CLIST(packet_list), i,
772 /* Save static column sizes to use during a "-S" capture, so that
773 the columns don't resize during a live capture. */
774 cf.cinfo.col_width[i] = get_column_width(get_column_format(i),
777 gtk_widget_set_usize(packet_list, -1, pl_size);
778 gtk_paned_add1(GTK_PANED(u_pane), packet_sw);
779 gtk_widget_show(packet_list);
782 tv_scrollw = gtk_scrolled_window_new(NULL, NULL);
783 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW(tv_scrollw),
784 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
785 gtk_paned_add1(GTK_PANED(l_pane), tv_scrollw);
786 gtk_widget_set_usize(tv_scrollw, -1, tv_size);
787 gtk_widget_show(tv_scrollw);
789 tree_view = gtk_tree_new();
790 gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(tv_scrollw),
792 gtk_tree_set_selection_mode(GTK_TREE(tree_view), GTK_SELECTION_SINGLE);
794 /* XXX - what's the difference between the next two lines? */
795 gtk_tree_set_view_lines(GTK_TREE(tree_view), FALSE);
796 gtk_tree_set_view_mode(GTK_TREE(tree_view), GTK_TREE_VIEW_ITEM);
798 gtk_signal_connect(GTK_OBJECT(tree_view), "selection_changed",
799 GTK_SIGNAL_FUNC(tree_view_cb), NULL);
800 gtk_widget_show(tree_view);
802 item_style = gtk_style_new();
803 gdk_font_unref(item_style->font);
804 item_style->font = m_r_font;
807 bv_table = gtk_table_new (2, 2, FALSE);
808 gtk_paned_add2(GTK_PANED(l_pane), bv_table);
809 gtk_widget_set_usize(bv_table, -1, bv_size);
810 gtk_widget_show(bv_table);
812 byte_view = gtk_text_new(NULL, NULL);
813 gtk_text_set_editable(GTK_TEXT(byte_view), FALSE);
814 gtk_text_set_word_wrap(GTK_TEXT(byte_view), FALSE);
815 gtk_table_attach (GTK_TABLE (bv_table), byte_view, 0, 1, 0, 1,
816 GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 0);
817 gtk_widget_show(byte_view);
819 bv_hscroll = gtk_hscrollbar_new(GTK_TEXT(byte_view)->hadj);
820 gtk_table_attach(GTK_TABLE(bv_table), bv_hscroll, 0, 1, 1, 2,
821 GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0);
822 gtk_widget_show (bv_hscroll);
824 bv_vscroll = gtk_vscrollbar_new(GTK_TEXT(byte_view)->vadj);
825 gtk_table_attach(GTK_TABLE(bv_table), bv_vscroll, 1, 2, 0, 1,
826 GTK_FILL, GTK_EXPAND | GTK_FILL | GTK_SHRINK, 0, 0);
827 gtk_widget_show(bv_vscroll);
829 /* Progress/filter/info box */
830 stat_hbox = gtk_hbox_new(FALSE, 1);
831 gtk_container_border_width(GTK_CONTAINER(stat_hbox), 0);
832 gtk_box_pack_start(GTK_BOX(main_vbox), stat_hbox, FALSE, TRUE, 0);
833 gtk_widget_show(stat_hbox);
835 prog_bar = gtk_progress_bar_new();
836 gtk_box_pack_start(GTK_BOX(stat_hbox), prog_bar, FALSE, TRUE, 3);
837 gtk_widget_show(prog_bar);
839 filter_bt = gtk_button_new_with_label("Filter:");
840 gtk_signal_connect(GTK_OBJECT(filter_bt), "clicked",
841 GTK_SIGNAL_FUNC(prefs_cb), (gpointer) E_PR_PG_FILTER);
842 gtk_box_pack_start(GTK_BOX(stat_hbox), filter_bt, FALSE, TRUE, 0);
843 gtk_widget_show(filter_bt);
845 filter_te = gtk_entry_new();
846 gtk_object_set_data(GTK_OBJECT(filter_bt), E_FILT_TE_PTR_KEY, filter_te);
847 gtk_box_pack_start(GTK_BOX(stat_hbox), filter_te, TRUE, TRUE, 3);
848 gtk_signal_connect(GTK_OBJECT(filter_te), "activate",
849 GTK_SIGNAL_FUNC(filter_activate_cb), (gpointer) NULL);
850 gtk_widget_show(filter_te);
852 /* Sets the text entry widget pointer as the E_DILTER_TE_KEY data
853 * of any widget that ends up calling a callback which needs
854 * that text entry pointer */
855 set_menu_object_data("/File/Open...", E_DFILTER_TE_KEY, filter_te);
856 set_menu_object_data("/File/Reload", E_DFILTER_TE_KEY, filter_te);
857 set_menu_object_data("/Display/Match Selected", E_DFILTER_TE_KEY,
860 info_bar = gtk_statusbar_new();
861 main_ctx = gtk_statusbar_get_context_id(GTK_STATUSBAR(info_bar), "main");
862 file_ctx = gtk_statusbar_get_context_id(GTK_STATUSBAR(info_bar), "file");
863 gtk_statusbar_push(GTK_STATUSBAR(info_bar), main_ctx, DEF_READY_MESSAGE);
864 gtk_box_pack_start(GTK_BOX(stat_hbox), info_bar, TRUE, TRUE, 0);
865 gtk_widget_show(info_bar);
868 Hmmm should we do it here
871 ethereal_proto_init(); /* Init anything that needs initializing */
873 gtk_widget_show(window);
877 /* If we were given the name of a capture file, read it in now;
878 we defer it until now, so that, if we can't open it, and pop
879 up an alert box, the alert box is more likely to come up on
880 top of the main window - but before the preference-file-error
881 alert box, so, if we get one of those, it's more likely to come
884 if (rfilter != NULL) {
885 rfcode = dfilter_new();
886 if (dfilter_compile(rfcode, rfilter) != 0) {
887 simple_dialog(ESD_TYPE_WARN, NULL, dfilter_error_msg);
888 dfilter_destroy(rfcode);
889 rfilter_parse_failed = TRUE;
892 if (!rfilter_parse_failed) {
893 if ((err = open_cap_file(cf_name, &cf)) == 0) {
895 err = read_cap_file(&cf);
896 s = strrchr(cf_name, '/');
898 last_open_dir = cf_name;
901 set_menu_sensitivity("/File/Save As...", TRUE);
906 /* If we failed to open the preferences file, pop up an alert box;
907 we defer it until now, so that the alert box is more likely to
908 come up on top of the main window. */
909 if (pf_path != NULL) {
910 simple_dialog(ESD_TYPE_WARN, NULL,
911 "Could not open preferences file\n\"%s\": %s.", pf_path,
912 strerror(pf_open_errno));
917 ethereal_proto_cleanup();