3 * $Id: ethereal.c,v 1.8 1998/10/16 06:44:32 guy Exp $
5 * Ethereal - Network traffic analyzer
6 * By Gerald Combs <gerald@zing.org>
7 * Copyright 1998 Gerald Combs
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.
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.
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.
26 * - Live browser/capture display
29 * - Check for end of packet in dissect_* routines.
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?
52 #include <sys/types.h>
55 #include <netinet/in.h>
69 FILE *data_out_file = NULL;
72 GtkWidget *file_sel, *packet_list, *tree_view, *byte_view, *prog_bar,
74 GdkFont *m_r_font, *m_b_font;
75 guint main_ctx, file_ctx;
77 gint start_capture = 0;
79 extern pr_opts printer_opts;
81 ts_type timestamp_type = RELATIVE;
83 #define E_DFILTER_TE_KEY "display_filter_te"
85 /* About Ethereal window */
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"
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);
103 /* Things to do when the OK button is pressed */
105 file_sel_ok_cb(GtkWidget *w, GtkFileSelection *fs) {
108 GtkWidget *filter_te = gtk_object_get_data(GTK_OBJECT(w), E_DFILTER_TE_KEY);
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));
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)
121 /* Update the progress bar */
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);
129 /* Follow a TCP stream */
131 follow_stream_cb( GtkWidget *w, gpointer data ) {
133 GtkWidget *streamwindow, *box, *text, *vscrollbar, *table;
134 GtkWidget *filter_te = gtk_object_get_data(GTK_OBJECT(w),
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 );
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 );
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 ) {
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 ) {
205 fclose( data_out_file );
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 );
216 simple_dialog(ESD_TYPE_WARN, NULL,
217 "Error following stream. Please make\n"
218 "sure you have a TCP packet selected.");
224 file_open_cmd_cb(GtkWidget *w, gpointer data) {
225 file_sel = gtk_file_selection_new ("Ethereal: Open Capture File");
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));
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));
239 gtk_file_selection_set_filename(GTK_FILE_SELECTION(file_sel), "");
241 gtk_widget_show(file_sel);
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);
252 /* Reload a file using the current display filter */
254 file_reload_cmd_cb(GtkWidget *w, gpointer data) {
255 GtkWidget *filter_te = gtk_object_get_data(GTK_OBJECT(w), E_DFILTER_TE_KEY);
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);
264 file_print_cmd_cb(GtkWidget *widget, gpointer data) {
265 print_tree(cf.pd, fd, GTK_TREE(tree_view));
268 /* What to do when a list item is selected/unselected */
270 packet_list_select_cb(GtkWidget *w, gint row, gint col, gpointer evt) {
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);
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);
287 gtk_text_thaw(GTK_TEXT(byte_view));
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));
302 tree_view_cb(GtkWidget *w) {
303 gint start = -1, len = -1;
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),
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));
321 file_quit_cmd_cb (GtkWidget *widget, gpointer data) {
325 void blank_packetinfo() {
333 /* Things to do when the OK button is pressed */
335 main_realize_cb(GtkWidget *w, gpointer data) {
336 gchar *cf_name = (gchar *) data;
340 err = load_cap_file(cf_name, &cf);
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",
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");
364 main(int argc, char *argv[])
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;
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",
377 gchar *medium_font = MONO_MEDIUM_FONT;
378 gchar *bold_font = MONO_BOLD_FONT;
380 /* Initialize the capture file struct */
391 /* Let GTK get its args */
392 gtk_init (&argc, &argv);
394 /* Now get our args */
395 while ((opt = getopt(argc, argv, "b:B:c:hi:m:nP:r:s:t:T:w:v")) != EOF) {
397 case 'b': /* Bold font */
398 bold_font = g_strdup(optarg);
400 case 'B': /* Byte view pane height */
401 bv_size = atoi(optarg);
403 case 'c': /* Capture xxx packets */
404 cf.count = atoi(optarg);
406 case 'h': /* Print help and exit */
410 case 'i': /* Use interface xxx */
411 cf.iface = g_strdup(optarg);
413 case 'm': /* Medium font */
414 medium_font = g_strdup(optarg);
416 case 'n': /* No name resolution */
417 g_resolving_actif = 0;
419 case 'k': /* Start capture immediately */
422 case 'P': /* Packet list pane height */
423 pl_size = atoi(optarg);
425 case 'r': /* Read capture file xxx */
426 cf_name = g_strdup(optarg);
428 case 's': /* Set the snapshot (capture) length */
429 cf.snap = atoi(optarg);
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;
439 fprintf(stderr, "ethereal: Invalid time stamp type \"%s\"\n",
441 fprintf(stderr, "It must be \"r\" for relative, \"a\" for absolute,\n");
442 fprintf(stderr, "or \"d\" for delta.\n");
446 case 'T': /* Tree view pane height */
447 tv_size = atoi(optarg);
449 case 'v': /* Show version and exit */
450 printf("%s %s\n", PACKAGE, VERSION);
453 case 'w': /* Write capture file xxx */
454 cf.save_file = g_strdup(optarg);
461 else if (cf.snap < 68)
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);
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");
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);
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);
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);
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);
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);
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);
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,
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");
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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,
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);
620 gtk_widget_show(window);