Added the ethereal capture preferences to the preference file.
[obnox/wireshark/wip.git] / gtk / main.c
index d7258ac449feabaed2b82a07d646bbd6dcaba239..a18182654a6422fdedba25d46427f1d09b8908bd 100644 (file)
@@ -1,13 +1,15 @@
 /* main.c
  *
- * $Id: main.c,v 1.125 2000/06/27 07:13:25 guy Exp $
+ * $Id: main.c,v 1.192 2001/04/13 14:59:30 jfoster Exp $
  *
  * Ethereal - Network traffic analyzer
- * By Gerald Combs <gerald@zing.org>
+ * By Gerald Combs <gerald@ethereal.com>
  * Copyright 1998 Gerald Combs
  *
  * Richard Sharpe, 13-Feb-1999, added support for initializing structures
  *                              needed by dissect routines
+ * Jeff Foster,    2001/03/12,  added support tabbed hex display windowss
+ * 
  * 
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
 #endif
 
 #include <errno.h>
+
+#ifdef HAVE_SYS_TYPES_H
 #include <sys/types.h>
+#endif
+
+#ifdef HAVE_SYS_STAT_H
 #include <sys/stat.h>
+#endif
 
 #ifdef HAVE_IO_H
 #include <io.h> /* open/close on win32 */
 
 #include <signal.h>
 
+#ifdef HAVE_LIBPCAP
+#include <pcap.h>
+#endif
+
 #ifdef NEED_SNPRINTF_H
-# ifdef HAVE_STDARG_H
-#  include <stdarg.h>
-# else
-#  include <varargs.h>
-# endif
 # include "snprintf.h"
 #endif
 
 #include "getopt.h"
 #endif
 
+#ifdef WIN32 /* Needed for console I/O */
+#include <fcntl.h>
+#include <conio.h>
+#endif
+
+#include <epan.h>
+#include <epan/filesystem.h>
+
 #include "main.h"
 #include "timestamp.h"
 #include "packet.h"
 #include "capture.h"
 #include "summary.h"
 #include "file.h"
+#include "filters.h"
 #include "menu.h"
 #include "../menu.h"
+#include "color.h"
+#include "color_utils.h"
 #include "filter_prefs.h"
 #include "prefs_dlg.h"
 #include "column.h"
 #include "print.h"
 #include "resolv.h"
-#include "follow.h"
 #include "util.h"
 #include "simple_dialog.h"
 #include "proto_draw.h"
-#include "dfilter.h"
+#include "dfilter/dfilter.h"
 #include "keys.h"
 #include "packet_win.h"
 #include "gtkglobals.h"
 #include "plugins.h"
+#include "colors.h"
+#include "strutil.h"
+#include "register.h"
+#include "prefs.h"
+
+#ifdef WIN32
+#include "capture-wpcap.h"
+#endif
+
 
-FILE        *data_out_file = NULL;
 packet_info  pi;
 capture_file cfile;
-GtkWidget   *top_level, *packet_list, *tree_view, *byte_view,
-            *prog_bar, *info_bar, *tv_scrollw, *pkt_scrollw;
+GtkWidget   *top_level, *packet_list, *tree_view, *byte_nb_ptr,
+            *info_bar, *tv_scrollw, *pkt_scrollw;
 static GtkWidget       *bv_scrollw;
 GdkFont     *m_r_font, *m_b_font;
-guint        main_ctx, file_ctx;
-gchar        comp_info_str[256];
+guint          m_font_height, m_font_width;
+guint        main_ctx, file_ctx, help_ctx;
+static GString *comp_info_str;
 gchar       *ethereal_path = NULL;
-gchar       *medium_font = MONO_MEDIUM_FONT;
-gchar       *bold_font = MONO_BOLD_FONT;
 gchar       *last_open_dir = NULL;
 
 ts_type timestamp_type = RELATIVE;
@@ -138,11 +162,15 @@ GtkStyle *item_style;
 /* Specifies the field currently selected in the GUI protocol tree */
 field_info *finfo_selected = NULL;
 
-static void follow_destroy_cb(GtkWidget *win, gpointer data);
-static void follow_charset_toggle_cb(GtkWidget *w, gpointer parent_w);
-static void follow_load_text(GtkWidget *text, char *filename, guint8 show_type);
-static void follow_print_stream(GtkWidget *w, gpointer parent_w);
-static char* hfinfo_numeric_format(header_field_info *hfinfo);
+#ifdef WIN32
+static gboolean has_no_console;        /* TRUE if app has no console */
+static gboolean console_was_created; /* TRUE if console was created */
+static void create_console(void);
+static void destroy_console(void);
+static void console_log_handler(const char *log_domain,
+    GLogLevelFlags log_level, const char *message, gpointer user_data);
+#endif
+
 static void create_main_window(gint, gint, gint, e_prefs*);
 
 /* About Ethereal window */
@@ -150,445 +178,29 @@ void
 about_ethereal( GtkWidget *w, gpointer data ) {
   simple_dialog(ESD_TYPE_INFO, NULL,
                "Ethereal - Network Protocol Analyzer\n"
-               "Version " VERSION " (C) 1998-2000 Gerald Combs <gerald@zing.org>\n"
-                "Compiled with %s\n\n"
+               "Version " VERSION " (C) 1998-2000 Gerald Combs <gerald@ethereal.com>\n"
+                "Compiled %s\n\n"
 
                "Check the man page for complete documentation and\n"
                "for the list of contributors.\n"
 
-               "\nSee http://ethereal.zing.org/ for more information.",
-                 comp_info_str);
+               "\nSee http://www.ethereal.com/ for more information.",
+                 comp_info_str->str);
 }
 
-/* Follow the TCP stream, if any, to which the last packet that we called
-   a dissection routine on belongs (this might be the most recently
-   selected packet, or it might be the last packet in the file). */
 void
-follow_stream_cb( GtkWidget *w, gpointer data ) {
-  char      filename1[128+1];
-  GtkWidget *streamwindow, *box, *txt_scrollw, *text, *filter_te;
-  GtkWidget *hbox, *close_bt, *print_bt;
-  GtkWidget *b_ascii, *b_ebcdic, *b_hexdump;
-  int        tmp_fd;
-  gchar     *follow_filter;
-
-  if( pi.ipproto == 6 ) {
-    /* we got tcp so we can follow */
-    /* Create a temporary file into which to dump the reassembled data
-       from the TCP stream, and set "data_out_file" to refer to it, so
-       that the TCP code will write to it.
-
-       XXX - it might be nicer to just have the TCP code directly
-       append stuff to the text widget for the TCP stream window,
-       if we can arrange that said window not pop up until we're
-       done. */
-    tmp_fd = create_tempfile( filename1, sizeof filename1, "follow");
-    if (tmp_fd == -1) {
-      simple_dialog(ESD_TYPE_WARN, NULL,
-        "Could not create temporary file %s: %s", filename1, strerror(errno));
-      return;
-    }
-    data_out_file = fdopen( tmp_fd, "wb" );
-    if( data_out_file == NULL ) {
-      simple_dialog(ESD_TYPE_WARN, NULL,
-        "Could not create temporary file %s: %s", filename1, strerror(errno));
-      close(tmp_fd);
-      unlink(filename1);
-      return;
-    }
-
-    /* Create a new filter that matches all packets in the TCP stream,
-       and set the display filter entry accordingly */
-    reset_tcp_reassembly();
-    follow_filter = build_follow_filter( &pi );
-
-    /* set the display filter entry accordingly */
-    filter_te = gtk_object_get_data(GTK_OBJECT(w), E_DFILTER_TE_KEY);
-    gtk_entry_set_text(GTK_ENTRY(filter_te), follow_filter);
-
-    /* Run the display filter so it goes in effect. */
-    filter_packets(&cfile, follow_filter);
-
-    /* the data_out_file should now be full of the streams information */
-    fclose( data_out_file );
-
-    /* the filename1 file now has all the text that was in the session */
-    streamwindow = gtk_window_new( GTK_WINDOW_TOPLEVEL);
-    gtk_widget_set_name( streamwindow, "TCP stream window" );
-
-    gtk_signal_connect( GTK_OBJECT(streamwindow), "destroy",
-                       GTK_SIGNAL_FUNC(follow_destroy_cb), NULL);
-                       
-    if( incomplete_tcp_stream ) {
-      gtk_window_set_title( GTK_WINDOW(streamwindow), 
-                           "Contents of TCP stream (incomplete)" );
-    } else {
-      gtk_window_set_title( GTK_WINDOW(streamwindow),
-                           "Contents of TCP stream" );
-    }
-    gtk_widget_set_usize( GTK_WIDGET(streamwindow), DEF_WIDTH, DEF_HEIGHT );
-    gtk_container_border_width( GTK_CONTAINER(streamwindow), 2 );
-
-    /* setup the container */
-    box = gtk_vbox_new( FALSE, 0 );
-    gtk_container_add( GTK_CONTAINER(streamwindow), box );
-    gtk_widget_show( box );
-
-    /* create a scrolled window for the text */
-    txt_scrollw = gtk_scrolled_window_new( NULL, NULL );
-    gtk_box_pack_start( GTK_BOX(box), txt_scrollw, TRUE, TRUE, 0 );
-    gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW(txt_scrollw),
-                                       GTK_POLICY_NEVER,
-                                       GTK_POLICY_ALWAYS );
-    set_scrollbar_placement_scrollw(txt_scrollw, prefs.gui_scrollbar_on_right);
-    remember_scrolled_window(txt_scrollw);
-    gtk_widget_show( txt_scrollw );
-
-    /* create a text box */
-    text = gtk_text_new( NULL, NULL );
-    gtk_text_set_editable( GTK_TEXT(text), FALSE);
-    gtk_container_add( GTK_CONTAINER(txt_scrollw), text );
-    gtk_widget_show(text);
-
-    /* Create hbox */
-    hbox = gtk_hbox_new( FALSE, 1 );
-    gtk_box_pack_end( GTK_BOX(box), hbox, FALSE, FALSE, 0);
-    gtk_widget_show(hbox);
-
-#define E_FOLLOW_ASCII_KEY "follow_ascii_key"
-#define E_FOLLOW_EBCDIC_KEY "follow_ebcdic_key"
-#define E_FOLLOW_HEXDUMP_KEY "follow_hexdump_key"
-
-    /* Create Radio Buttons */
-    b_ascii = gtk_radio_button_new_with_label(NULL, "ASCII");
-    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(b_ascii), TRUE);
-    gtk_object_set_data(GTK_OBJECT(streamwindow), E_FOLLOW_ASCII_KEY, b_ascii);
-    gtk_box_pack_start(GTK_BOX(hbox), b_ascii, FALSE, FALSE, 0);
-    gtk_signal_connect(GTK_OBJECT(b_ascii), "toggled",
-                   GTK_SIGNAL_FUNC(follow_charset_toggle_cb),
-                   GTK_OBJECT(streamwindow));
-    gtk_widget_show(b_ascii);
-
-    b_ebcdic = gtk_radio_button_new_with_label(
-                   gtk_radio_button_group(GTK_RADIO_BUTTON(b_ascii)),
-                   "EBCDIC");
-    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(b_ebcdic), FALSE);
-    gtk_object_set_data(GTK_OBJECT(streamwindow), E_FOLLOW_EBCDIC_KEY, b_ebcdic);
-    gtk_box_pack_start(GTK_BOX(hbox), b_ebcdic, FALSE, FALSE, 0);
-    gtk_signal_connect(GTK_OBJECT(b_ebcdic), "toggled",
-                   GTK_SIGNAL_FUNC(follow_charset_toggle_cb),
-                   GTK_OBJECT(streamwindow));
-    gtk_widget_show(b_ebcdic);
-
-    b_hexdump = gtk_radio_button_new_with_label(
-                   gtk_radio_button_group(GTK_RADIO_BUTTON(b_ascii)),
-                   "Hex. Dump");
-    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(b_hexdump), FALSE);
-    gtk_object_set_data(GTK_OBJECT(streamwindow), E_FOLLOW_HEXDUMP_KEY, b_hexdump);
-    gtk_box_pack_start(GTK_BOX(hbox), b_hexdump, FALSE, FALSE, 0);
-    gtk_signal_connect(GTK_OBJECT(b_hexdump), "toggled",
-                   GTK_SIGNAL_FUNC(follow_charset_toggle_cb),
-                   GTK_OBJECT(streamwindow));
-    gtk_widget_show(b_hexdump);
-
-    /* Create Close Button */
-    close_bt = gtk_button_new_with_label("Close");
-    gtk_signal_connect_object(GTK_OBJECT(close_bt), "clicked",
-                   GTK_SIGNAL_FUNC(gtk_widget_destroy),
-                   GTK_OBJECT(streamwindow));
-    gtk_box_pack_end( GTK_BOX(hbox), close_bt, FALSE, FALSE, 0);
-    gtk_widget_show( close_bt );
-
-    /* Create Print Button */
-    print_bt = gtk_button_new_with_label("Print");
-    gtk_signal_connect(GTK_OBJECT(print_bt), "clicked",
-                   GTK_SIGNAL_FUNC(follow_print_stream),
-                   GTK_OBJECT(streamwindow));
-    gtk_box_pack_end( GTK_BOX(hbox), print_bt, FALSE, FALSE, 0);
-    gtk_widget_show( print_bt );
-
-    /* Tuck away the filename and textbox into streamwindow */
-#define E_FOLLOW_FILENAME_KEY "follow_filename_key"
-#define E_FOLLOW_TEXT_KEY "follow_text_key"
-
-    gtk_object_set_data(GTK_OBJECT(streamwindow), E_FOLLOW_FILENAME_KEY,
-                   g_strdup(filename1));
-    gtk_object_set_data(GTK_OBJECT(streamwindow), E_FOLLOW_TEXT_KEY, text);
-
-    follow_load_text(text, filename1, 0);
-
-    data_out_file = NULL;
-
-    /* Make sure this widget gets destroyed if we quit the main loop,
-       so that if we exit, we clean up any temporary files we have
-       for "Follow TCP Stream" windows. */
-    gtk_quit_add_destroy(gtk_main_level(), GTK_OBJECT(streamwindow));
-    gtk_widget_show( streamwindow );
-  } else {
-    simple_dialog(ESD_TYPE_WARN, NULL,
-      "Error following stream.  Please make\n"
-      "sure you have a TCP packet selected.");
-  }
-}
-
-/* The destroy call back has the responsibility of
- * unlinking the temporary file */
-static void
-follow_destroy_cb(GtkWidget *win, gpointer data)
-{
-       char    *filename;
-
-       filename = (char*) gtk_object_get_data(GTK_OBJECT(win),
-                                               E_FOLLOW_FILENAME_KEY);
-       g_assert(filename);
-
-       unlink(filename);
-       gtk_widget_destroy(win);
-}
-
-#define E_FOLLOW_ASCII_TYPE    0
-#define E_FOLLOW_EBCDIC_TYPE   1
-#define E_FOLLOW_HEXDUMP_TYPE  2
-
-/* Handles the ASCII/EBCDIC toggling */
-static void
-follow_charset_toggle_cb(GtkWidget *w, gpointer parent_w)
-{
-       guint8          show_type = E_FOLLOW_ASCII_TYPE;
-       GtkWidget       *b_ascii, *b_ebcdic, *b_hexdump, *text;
-       char            *filename;
-
-       b_ascii = (GtkWidget*) gtk_object_get_data(GTK_OBJECT(parent_w),
-                                                  E_FOLLOW_ASCII_KEY);
-       b_ebcdic = (GtkWidget*) gtk_object_get_data(GTK_OBJECT(parent_w),
-                                                   E_FOLLOW_EBCDIC_KEY);
-       b_hexdump = (GtkWidget*) gtk_object_get_data(GTK_OBJECT(parent_w),
-                                                    E_FOLLOW_HEXDUMP_KEY);
-       text = (GtkWidget*) gtk_object_get_data(GTK_OBJECT(parent_w),
-                                               E_FOLLOW_TEXT_KEY);
-       filename = (char*) gtk_object_get_data(GTK_OBJECT(parent_w),
-                                               E_FOLLOW_FILENAME_KEY);
-
-       g_assert(b_ascii);
-       g_assert(b_ebcdic);
-       g_assert(b_hexdump);
-       g_assert(text);
-       g_assert(filename);
-
-       if (GTK_TOGGLE_BUTTON(b_ebcdic)->active)
-               show_type = E_FOLLOW_EBCDIC_TYPE;
-       else if (GTK_TOGGLE_BUTTON(b_hexdump)->active)
-               show_type = E_FOLLOW_HEXDUMP_TYPE;
-
-       follow_load_text(text, filename, show_type);
-}
-
-#define FLT_BUF_SIZE 1024
-static void
-follow_read_stream(char *filename, guint8 show_type,
-   void (*print_line)(char *, int, gboolean, void *), void *arg)
-{
-  tcp_stream_chunk sc;
-  int bcount;
-  guint32 client_addr = 0;
-  guint16 client_port = 0;
-  gboolean is_server;
-  guint16 current_pos, global_client_pos = 0, global_server_pos = 0;
-  guint16 *global_pos;
-
-  data_out_file = fopen( filename, "rb" );
-  if( data_out_file ) {
-    char buffer[FLT_BUF_SIZE];
-    int nchars;
-    while(fread(&sc.src_addr, 1, sizeof(sc), data_out_file)) {
-      if (client_addr == 0) {
-        client_addr = sc.src_addr;
-        client_port = sc.src_port;
-      }
-      if (client_addr == sc.src_addr && client_port == sc.src_port) {
-       is_server = FALSE;
-       global_pos = &global_client_pos;
-      }
-      else {
-       is_server = TRUE;
-       global_pos = &global_server_pos;
-      }
-        
-      while (sc.dlen > 0) {
-        bcount = (sc.dlen < FLT_BUF_SIZE) ? sc.dlen : FLT_BUF_SIZE;
-        nchars = fread( buffer, 1, bcount, data_out_file );
-        if (nchars == 0)
-          break;
-        sc.dlen -= bcount;
-       switch (show_type) {
-       case E_FOLLOW_EBCDIC_TYPE:
-               /* If our native arch is ASCII, call: */
-               EBCDIC_to_ASCII(buffer, nchars);
-       case E_FOLLOW_ASCII_TYPE:
-               /* If our native arch is EBCDIC, call:
-                * ASCII_TO_EBCDIC(buffer, nchars);
-                */
-               (*print_line)( buffer, nchars, is_server, arg );
-               break;
-       case E_FOLLOW_HEXDUMP_TYPE:
-               current_pos = 0;
-               while (current_pos < nchars)
-               {
-                   gchar hexbuf[256];
-                   gchar hexchars[] = "0123456789abcdef";
-                   int i, cur;
-                   /* is_server indentation : put 63 spaces at the begenning
-                    * of the string */
-                   sprintf(hexbuf, is_server ?
-                           "                                 "
-                           "                              %08X  " :
-                           "%08X  ", *global_pos);
-                   cur = strlen(hexbuf);
-                   for (i=0; i < 16 && current_pos+i < nchars; i++) {
-                       hexbuf[cur++] = hexchars[(buffer[current_pos+i] & 0xf0) >> 4];
-                       hexbuf[cur++] = hexchars[buffer[current_pos+i] & 0x0f];
-                       if (i == 7) {
-                           hexbuf[cur++] = ' '; hexbuf[cur++] = ' ';
-                       }
-                       else if (i != 15)
-                           hexbuf[cur++] = ' ';
-                   }
-                   current_pos += i;
-                   (*global_pos) += i;
-                   hexbuf[cur++] = '\n';
-                   hexbuf[cur] = 0;
-                   (*print_line)( hexbuf, strlen(hexbuf), is_server, arg );
-               }
-               break;
-       }
-      }
-    }
-    if( ferror( data_out_file ) ) {
-      simple_dialog(ESD_TYPE_WARN, NULL,
-        "Error reading temporary file %s: %s", filename, strerror(errno));
-    }
-    fclose( data_out_file );
-    data_out_file = NULL;
-  } else {
-    simple_dialog(ESD_TYPE_WARN, NULL,
-      "Could not open temporary file %s: %s", filename, strerror(errno));
-  }
-}
-
-/*
- * XXX - for text printing, we probably want to wrap lines at 80 characters;
- * for PostScript printing, we probably want to wrap them at the appropriate
- * width, and perhaps put some kind of dingbat (to use the technical term)
- * to indicate a wrapped line, along the lines of what's done when displaying
- * this in a window, as per Warren Young's suggestion.
- *
- * For now, we support only text printing.
- */
-static void
-follow_print_text(char *buffer, int nchars, gboolean is_server, void *arg)
-{
-  FILE *fh = arg;
-
-  fwrite(buffer, nchars, 1, fh);
-}
-
-static void
-follow_print_stream(GtkWidget *w, gpointer parent_w)
+set_fonts(GdkFont *regular, GdkFont *bold)
 {
-       FILE *fh;
-       gboolean to_file;
-       char* print_dest;
-       char* filename;
-       guint8 show_type = E_FOLLOW_ASCII_TYPE;
-       GtkWidget *button;
-
-       switch (prefs.pr_dest) {
-               case PR_DEST_CMD:
-                       print_dest = prefs.pr_cmd;
-                       to_file = FALSE;
-                       break;
-
-               case PR_DEST_FILE:
-                       print_dest = prefs.pr_file;
-                       to_file = TRUE;
-                       break;
-               default: /* "Can't happen" */
-                       simple_dialog(ESD_TYPE_WARN, NULL,
-                               "Couldn't figure out where to send the print "
-                               "job. Check your preferences.");
-                       return;
-       }
-
-       fh = open_print_dest(to_file, print_dest);
-       if (fh == NULL) {
-               switch (to_file) {
-                       case FALSE:
-                               simple_dialog(ESD_TYPE_WARN, NULL,
-                                               "Couldn't run print command %s.", prefs.pr_cmd);
-                               break;
-
-                       case TRUE:
-                               simple_dialog(ESD_TYPE_WARN, NULL, 
-                                               file_write_error_message(errno),
-                                               prefs.pr_file);
-                               break;
-               }
-               return;
-       }
-
-       button = (GtkWidget*) gtk_object_get_data(GTK_OBJECT(parent_w),
-                       E_FOLLOW_EBCDIC_KEY);
-       if (GTK_TOGGLE_BUTTON(button)->active)
-               show_type = E_FOLLOW_EBCDIC_TYPE;
-       button = (GtkWidget*) gtk_object_get_data(GTK_OBJECT(parent_w),
-                       E_FOLLOW_HEXDUMP_KEY);
-       if (GTK_TOGGLE_BUTTON(button)->active)
-               show_type = E_FOLLOW_HEXDUMP_TYPE;
-
-       filename = (char*) gtk_object_get_data(GTK_OBJECT(parent_w),
-                       E_FOLLOW_FILENAME_KEY);
-
-       if (filename != NULL) {
-               print_preamble(fh, PR_FMT_TEXT);
-               follow_read_stream(filename, show_type, follow_print_text, fh);
-               print_finale(fh, PR_FMT_TEXT);
-               close_print_dest(to_file, fh);
-       }
-       else {
-               simple_dialog(ESD_TYPE_WARN, NULL, "Could not find data to print.");
-       }
+       /* Yes, assert. The code that loads the font should check
+        * for NULL and provide its own error message. */
+       g_assert(m_r_font && m_b_font);
+       m_r_font = regular;
+       m_b_font = bold;
+
+       m_font_height = m_r_font->ascent + m_r_font->descent;
+       m_font_width = gdk_string_width(m_r_font, "0");
 }
 
-static void
-follow_add_to_gtk_text(char *buffer, int nchars, gboolean is_server, void *arg)
-{
-  GtkWidget *text = arg;
-
-  if (is_server)
-    gtk_text_insert( GTK_TEXT(text), m_r_font, &prefs.st_server_fg,
-            &prefs.st_server_bg, buffer, nchars );
-  else
-    gtk_text_insert( GTK_TEXT(text), m_r_font, &prefs.st_client_fg,
-            &prefs.st_client_bg, buffer, nchars );
-}
-
-static void
-follow_load_text(GtkWidget *text, char *filename, guint8 show_type)
-{
-  int bytes_already;
-
-  /* Delete any info already in text box */
-  bytes_already = gtk_text_get_length(GTK_TEXT(text));
-  if (bytes_already > 0) {
-    gtk_text_set_point(GTK_TEXT(text), 0);
-    gtk_text_forward_delete(GTK_TEXT(text), bytes_already);
-  }
-
-  /* stop the updates while we fill the text box */
-  gtk_text_freeze( GTK_TEXT(text) );
-  follow_read_stream(filename, show_type, follow_add_to_gtk_text, text);
-  gtk_text_thaw( GTK_TEXT(text) );
-}
 
 /* Match selected byte pattern */
 void
@@ -596,125 +208,18 @@ match_selected_cb(GtkWidget *w, gpointer data)
 {
     char               *buf;
     GtkWidget          *filter_te;
-    char               *ptr, *format, *stringified;
-    int                        i, dfilter_len, abbrev_len;
-    guint8             *c;
-    header_field_info  *hfinfo;
 
     filter_te = gtk_object_get_data(GTK_OBJECT(w), E_DFILTER_TE_KEY);
 
     if (!finfo_selected) {
-       simple_dialog(ESD_TYPE_WARN, NULL,
+       simple_dialog(ESD_TYPE_CRIT, NULL,
                      "Error determining selected bytes.  Please make\n"
                      "sure you have selected a field within the tree\n"
                      "view to be matched.");
        return;
     }
 
-    hfinfo = finfo_selected->hfinfo;
-    g_assert(hfinfo);
-    abbrev_len = strlen(hfinfo->abbrev);
-
-       switch(hfinfo->type) {
-
-               case FT_BOOLEAN:
-                       dfilter_len = abbrev_len + 2;
-                       buf = g_malloc0(dfilter_len);
-                       snprintf(buf, dfilter_len, "%s%s", finfo_selected->value.numeric ? "" : "!",
-                                       hfinfo->abbrev);
-                       break;
-
-               case FT_UINT8:
-               case FT_UINT16:
-               case FT_UINT24:
-               case FT_UINT32:
-               case FT_INT8:
-               case FT_INT16:
-               case FT_INT24:
-               case FT_INT32:
-                       dfilter_len = abbrev_len + 20;
-                       buf = g_malloc0(dfilter_len);
-                       format = hfinfo_numeric_format(hfinfo);
-                       snprintf(buf, dfilter_len, format, hfinfo->abbrev, finfo_selected->value.numeric);
-                       break;
-
-               case FT_IPv4:
-                       dfilter_len = abbrev_len + 4 + 15 + 1;
-                       buf = g_malloc0(dfilter_len);
-                       snprintf(buf, dfilter_len, "%s == %s", hfinfo->abbrev,
-                                       ipv4_addr_str(&(finfo_selected->value.ipv4)));
-                       break;
-
-               case FT_IPXNET:
-                       dfilter_len = abbrev_len + 15;
-                       buf = g_malloc0(dfilter_len);
-                       snprintf(buf, dfilter_len, "%s == 0x%08x", hfinfo->abbrev,
-                                       finfo_selected->value.numeric);
-                       break;
-
-               case FT_IPv6:
-                       stringified = ip6_to_str((struct e_in6_addr*) &(finfo_selected->value.ipv6));
-                       dfilter_len = abbrev_len + 4 + strlen(stringified) + 1;
-                       buf = g_malloc0(dfilter_len);
-                       snprintf(buf, dfilter_len, "%s == %s", hfinfo->abbrev,
-                                       stringified);
-                       break;
-
-               case FT_DOUBLE:
-                       dfilter_len = abbrev_len + 30;
-                       buf = g_malloc0(dfilter_len);
-                       snprintf(buf, dfilter_len, "%s == %f", hfinfo->abbrev,
-                                       finfo_selected->value.floating);
-                       break;
-
-               case FT_ETHER:
-                       dfilter_len = abbrev_len + 22;
-                       buf = g_malloc0(dfilter_len);
-                       snprintf(buf, dfilter_len, "%s == %s",
-                                       hfinfo->abbrev,
-                                       ether_to_str(finfo_selected->value.ether));
-                       break;
-#if 0
-
-               case FT_ABSOLUTE_TIME:
-               case FT_RELATIVE_TIME:
-                       memcpy(&fi->value.time, va_arg(ap, struct timeval*),
-                               sizeof(struct timeval));
-                       break;
-
-               case FT_STRING:
-                       /* This g_strdup'ed memory is freed in proto_tree_free_node() */
-                       fi->value.string = g_strdup(va_arg(ap, char*));
-                       break;
-
-               case FT_TEXT_ONLY:
-                       ; /* nothing */
-                       break;
-#endif
-               default:
-                   c = cfile.pd + finfo_selected->start;
-                   buf = g_malloc0(32 + finfo_selected->length * 3);
-                   ptr = buf;
-
-                   sprintf(ptr, "frame[%d] == ", finfo_selected->start);
-                   ptr = buf+strlen(buf);
-
-                   if (finfo_selected->length == 1) {
-                       sprintf(ptr, "0x%02x", *c++);
-                   }
-                   else {
-                           for (i=0;i<finfo_selected->length; i++) {
-                               if (i == 0 ) {
-                                       sprintf(ptr, "%02x", *c++);
-                               }
-                               else {
-                                       sprintf(ptr, ":%02x", *c++);
-                               }
-                               ptr = buf+strlen(buf);
-                           }
-                   }
-                   break;
-       }
+    buf = proto_alloc_dfilter_string(finfo_selected, cfile.pd);
 
     /* create a new one and set the display filter entry accordingly */
     gtk_entry_set_text(GTK_ENTRY(filter_te), buf);
@@ -725,60 +230,6 @@ match_selected_cb(GtkWidget *w, gpointer data)
     /* Don't g_free(buf) here. filter_packets() will do it the next time it's called */
 }
 
-static char*
-hfinfo_numeric_format(header_field_info *hfinfo)
-{
-       char *format = NULL;
-
-       /* Pick the proper format string */
-       switch(hfinfo->display) {
-               case BASE_DEC:
-               case BASE_NONE:
-               case BASE_OCT: /* I'm lazy */
-               case BASE_BIN: /* I'm lazy */
-                       switch(hfinfo->type) {
-                               case FT_UINT8:
-                               case FT_UINT16:
-                               case FT_UINT24:
-                               case FT_UINT32:
-                                       format = "%s == %u";
-                                       break;
-                               case FT_INT8:
-                               case FT_INT16:
-                               case FT_INT24:
-                               case FT_INT32:
-                                       format = "%s == %d";
-                                       break;
-                               default:
-                                       g_assert_not_reached();
-                                       ;
-                       }
-                       break;
-               case BASE_HEX:
-                       switch(hfinfo->type) {
-                               case FT_UINT8:
-                                       format = "%s == 0x%02x";
-                                       break;
-                               case FT_UINT16:
-                                       format = "%s == 0x%04x";
-                                       break;
-                               case FT_UINT24:
-                                       format = "%s == 0x%06x";
-                                       break;
-                               case FT_UINT32:
-                                       format = "%s == 0x%08x";
-                                       break;
-                               default:
-                                       g_assert_not_reached();
-                                       ;
-                       }
-                       break;
-               default:
-                       g_assert_not_reached();
-                       ;
-       }
-       return format;
-}
 
 
 /* Run the current display filter on the current packet set, and
@@ -893,40 +344,168 @@ packet_list_click_column_cb(GtkCList *clist, gint column, gpointer data)
   gtk_clist_sort(clist);
 }
 
+/* mark packets */
+static void 
+set_frame_mark(gboolean set, frame_data *frame, gint row) {
+  GdkColor fg, bg;
+
+  if (frame == NULL || row == -1) return;
+  frame->flags.marked = set;
+  if (set) {
+    color_t_to_gdkcolor(&fg, &prefs.gui_marked_fg);
+    color_t_to_gdkcolor(&bg, &prefs.gui_marked_bg);
+  } else {
+    fg = BLACK;
+    bg = WHITE;
+  }
+  gtk_clist_set_background(GTK_CLIST(packet_list), row, &bg);
+  gtk_clist_set_foreground(GTK_CLIST(packet_list), row, &fg);
+}
+
+static void
+packet_list_button_pressed_cb(GtkWidget *w, GdkEvent *event, gpointer data) {
+  
+  GdkEventButton *event_button = (GdkEventButton *)event;
+  gint row, column;
+
+  if (w == NULL || event == NULL)
+    return;
+
+  if (event->type == GDK_BUTTON_PRESS && event_button->button == 2 &&
+      gtk_clist_get_selection_info(GTK_CLIST(w), event_button->x, event_button->y,
+                                  &row, &column)) {
+    frame_data *fdata = (frame_data *) gtk_clist_get_row_data(GTK_CLIST(w), row);
+    set_frame_mark(!fdata->flags.marked, fdata, row);
+  }
+}
+
+void mark_frame_cb(GtkWidget *w, gpointer data) {
+  if (cfile.current_frame) {
+    /* XXX hum, should better have a "cfile->current_row" here ... */
+    set_frame_mark(!cfile.current_frame->flags.marked,
+                  cfile.current_frame, 
+                  gtk_clist_find_row_from_data(GTK_CLIST(packet_list), 
+                                               cfile.current_frame));
+  }
+}
+
+static void mark_all_frames(gboolean set) {
+  frame_data *fdata;
+  if (cfile.plist == NULL) return;
+  for (fdata = cfile.plist; fdata != NULL; fdata = fdata->next) {
+    set_frame_mark(set,
+                  fdata,
+                  gtk_clist_find_row_from_data(GTK_CLIST(packet_list), fdata));    
+  }
+}
+
+void update_marked_frames(void) {
+  frame_data *fdata;
+  if (cfile.plist == NULL) return;
+  for (fdata = cfile.plist; fdata != NULL; fdata = fdata->next) {
+    if (fdata->flags.marked)
+      set_frame_mark(TRUE,
+                    fdata,
+                    gtk_clist_find_row_from_data(GTK_CLIST(packet_list),
+                                                 fdata));
+  }
+}
+
+void mark_all_frames_cb(GtkWidget *w, gpointer data) {
+  mark_all_frames(TRUE);
+}
+
+void unmark_all_frames_cb(GtkWidget *w, gpointer data) {
+  mark_all_frames(FALSE);
+}
+
 /* What to do when a list item is selected/unselected */
 static void
 packet_list_select_cb(GtkWidget *w, gint row, gint col, gpointer evt) {
 
   blank_packetinfo();
+
+/* Remove the hex display tabbed pages */
+  while( (gtk_notebook_get_nth_page( GTK_NOTEBOOK(byte_nb_ptr), 0)))
+    gtk_notebook_remove_page( GTK_NOTEBOOK(byte_nb_ptr), 0);
+
   select_packet(&cfile, row);
 }
 
+
 static void
 packet_list_unselect_cb(GtkWidget *w, gint row, gint col, gpointer evt) {
+
   unselect_packet(&cfile);
 }
 
+
 static void
 tree_view_select_row_cb(GtkCTree *ctree, GList *node, gint column, gpointer user_data)
 {
        field_info      *finfo;
+       gchar           *help_str = NULL;
+       gboolean        has_blurb = FALSE;
+       guint           length = 0, byte_len;
+       GtkWidget       *byte_view;
+       guint8          *byte_data;
 
        g_assert(node);
        finfo = gtk_ctree_node_get_row_data( ctree, GTK_CTREE_NODE(node) );
        if (!finfo) return;
 
+       set_notebook_page(  byte_nb_ptr, find_notebook_page( byte_nb_ptr, finfo->ds_name));
+
+        byte_view = gtk_object_get_data(GTK_OBJECT(byte_nb_ptr), E_BYTE_VIEW_TEXT_INFO_KEY);
+        byte_data = gtk_object_get_data(GTK_OBJECT(byte_view), E_BYTE_VIEW_DATA_PTR_KEY);
+        byte_len = GPOINTER_TO_INT(gtk_object_get_data(GTK_OBJECT(byte_view), E_BYTE_VIEW_DATA_LEN_KEY));
+
+       g_assert(byte_data);
+
        finfo_selected = finfo;
 
-       packet_hex_print(GTK_TEXT(byte_view), cfile.pd, cfile.current_frame->cap_len, 
-               finfo->start, finfo->length, cfile.current_frame->flags.encoding);
+       set_menus_for_selected_tree_row(TRUE);
+
+       /*if (finfo->hfinfo && finfo->hfinfo->type != FT_TEXT_ONLY) {*/
+       if (finfo->hfinfo) {
+         if (finfo->hfinfo->blurb != NULL && 
+             finfo->hfinfo->blurb[0] != '\0') {
+           has_blurb = TRUE;
+           length = strlen(finfo->hfinfo->blurb);
+         } else {
+           length = strlen(finfo->hfinfo->name);
+         }
+         length += strlen(finfo->hfinfo->abbrev) + 10;
+         help_str = g_malloc(sizeof(gchar) * length);
+         sprintf(help_str, "%s (%s)", 
+                 (has_blurb) ? finfo->hfinfo->blurb : finfo->hfinfo->name,
+                 finfo->hfinfo->abbrev);
+         gtk_statusbar_push(GTK_STATUSBAR(info_bar), help_ctx, help_str);
+         g_free(help_str);
+       }
+
+       packet_hex_print(GTK_TEXT(byte_view), byte_data, cfile.current_frame,
+               finfo, byte_len);
 }
 
 static void
 tree_view_unselect_row_cb(GtkCTree *ctree, GList *node, gint column, gpointer user_data)
 {
+       GtkWidget       *byte_view;
+       guint8  *data;
+       gint    len;    
+       field_info* fi;
+
+       fi = (field_info*)user_data;
+
+       len = get_byte_view_and_data( byte_nb_ptr, &byte_view, &data);
+
+       if ( len < 0) return;
+       gtk_statusbar_pop(GTK_STATUSBAR(info_bar), help_ctx);
        finfo_selected = NULL;
-       packet_hex_print(GTK_TEXT(byte_view), cfile.pd, cfile.current_frame->cap_len, 
-               -1, -1, cfile.current_frame->flags.encoding);
+       set_menus_for_selected_tree_row(FALSE);
+       packet_hex_print(GTK_TEXT(byte_view), data, cfile.current_frame,
+               NULL, len);
 }
 
 void collapse_all_cb(GtkWidget *widget, gpointer data) {
@@ -941,11 +520,11 @@ void expand_all_cb(GtkWidget *widget, gpointer data) {
 
 void resolve_name_cb(GtkWidget *widget, gpointer data) {
   if (cfile.protocol_tree) {
-    int tmp = g_resolving_actif;
-    g_resolving_actif = 1;
+    int tmp = prefs.capture_name_resolve;
+    prefs.capture_name_resolve = 1;
     gtk_clist_clear ( GTK_CLIST(tree_view) );
     proto_tree_draw(cfile.protocol_tree, tree_view);
-    g_resolving_actif = tmp;
+    prefs.capture_name_resolve = tmp;
   }
 }
 
@@ -968,15 +547,22 @@ set_scrollbar_placement_scrollw(GtkWidget *scrollw, int pos) /* 0=left, 1=right
 static GList *scrolled_windows;
 
 /* Add a scrolled window to the list of scrolled windows. */
+static void forget_scrolled_window(GtkWidget *scrollw, gpointer data);
+
 void
 remember_scrolled_window(GtkWidget *scrollw)
 {
   scrolled_windows = g_list_append(scrolled_windows, scrollw);
+
+  /* Catch the "destroy" event on the widget, so that we remove it from
+     the list when it's destroyed. */
+  gtk_signal_connect(GTK_OBJECT(scrollw), "destroy",
+                    GTK_SIGNAL_FUNC(forget_scrolled_window), NULL);
 }
 
 /* Remove a scrolled window from the list of scrolled windows. */
-void
-forget_scrolled_window(GtkWidget *scrollw)
+static void
+forget_scrolled_window(GtkWidget *scrollw, gpointer data)
 {
   scrolled_windows = g_list_remove(scrolled_windows, scrollw);
 }
@@ -1000,6 +586,29 @@ set_scrollbar_placement_all(int pos)
 void
 set_plist_sel_browse(gboolean val)
 {
+       gboolean old_val;
+
+       old_val =
+           (GTK_CLIST(packet_list)->selection_mode == GTK_SELECTION_SINGLE);
+
+       if (val == old_val) {
+               /*
+                * The mode isn't changing, so don't do anything.
+                * In particular, don't gratuitiously unselect the
+                * current packet.
+                *
+                * XXX - why do we have to unselect the current packet
+                * ourselves?  The documentation for the GtkCList at
+                *
+                *      http://developer.gnome.org/doc/API/gtk/gtkclist.html
+                *
+                * says "Note that setting the widget's selection mode to
+                * one of GTK_SELECTION_BROWSE or GTK_SELECTION_SINGLE will
+                * cause all the items in the GtkCList to become deselected."
+                */
+               return;
+       }
+
        if (finfo_selected)
                unselect_packet(&cfile);
 
@@ -1012,66 +621,27 @@ set_plist_sel_browse(gboolean val)
                gtk_clist_set_selection_mode(GTK_CLIST(packet_list), GTK_SELECTION_BROWSE);
        }
 }
-
-/* Set the selection mode of a given packet tree window. */
-void
-set_ptree_sel_browse(GtkWidget *tv, gboolean val)
-{
-       /* Yeah, GTK uses "browse" in the case where we do not, but oh well. I think
-        * "browse" in Ethereal makes more sense than "SINGLE" in GTK+ */
-       if (val) {
-               gtk_clist_set_selection_mode(GTK_CLIST(tv), GTK_SELECTION_SINGLE);
-       }
-       else {
-               gtk_clist_set_selection_mode(GTK_CLIST(tv), GTK_SELECTION_BROWSE);
-       }
-}
-
-/* Set the selection mode of all packet tree windows. */
+       
+/* Set the font of the packet list window. */
 void
-set_ptree_sel_browse_all(gboolean val)
+set_plist_font(GdkFont *font)
 {
-       set_ptree_sel_browse(tree_view, val);
-       set_ptree_sel_browse_packet_wins(val);
-}
+       GtkStyle *style;
+       int i;
 
-/* Set the line style of a given packet tree window. */
-void
-set_ptree_line_style(GtkWidget *tv, gint style)
-{
-       /* I'm using an assert here since the preferences code limits
-        * the user input, both in the GUI and when reading the preferences file.
-        * If the value is incorrect, it's a program error, not a user-initiated error.
-        */
-       g_assert(style >= GTK_CTREE_LINES_NONE && style <= GTK_CTREE_LINES_TABBED);
-       gtk_ctree_set_line_style( GTK_CTREE(tv), style );
-}
+       style = gtk_style_new();
+       gdk_font_unref(style->font);
+       style->font = font;
+       gdk_font_ref(font);
 
-/* Set the line style of all packet tree window. */
-void
-set_ptree_line_style_all(gint style)
-{
-       set_ptree_line_style(tree_view, style);
-       set_ptree_line_style_packet_wins(style);
-}
+       gtk_widget_set_style(packet_list, style);
 
-/* Set the expander style of a given packet tree window. */
-void
-set_ptree_expander_style(GtkWidget *tv, gint style)
-{
-       /* I'm using an assert here since the preferences code limits
-        * the user input, both in the GUI and when reading the preferences file.
-        * If the value is incorrect, it's a program error, not a user-initiated error.
-        */
-       g_assert(style >= GTK_CTREE_EXPANDER_NONE && style <= GTK_CTREE_EXPANDER_CIRCULAR);
-       gtk_ctree_set_expander_style( GTK_CTREE(tv), style );
-}
-       
-void
-set_ptree_expander_style_all(gint style)
-{
-       set_ptree_expander_style(tree_view, style);
-       set_ptree_expander_style_packet_wins(style);
+       /* Compute static column sizes to use during a "-S" capture, so that
+          the columns don't resize during a live capture. */
+       for (i = 0; i < cfile.cinfo.num_cols; i++) {
+               cfile.cinfo.col_width[i] = gdk_string_width(font,
+                       get_column_longest_string(get_column_format(i)));
+       }
 }
 
 static gboolean
@@ -1138,24 +708,34 @@ file_quit_cmd_cb (GtkWidget *widget, gpointer data)
 static void 
 print_usage(void) {
 
-  fprintf(stderr, "This is GNU " PACKAGE " " VERSION ", compiled with %s\n",
-         comp_info_str);
+  fprintf(stderr, "This is GNU " PACKAGE " " VERSION ", compiled %s\n",
+         comp_info_str->str);
 #ifdef HAVE_LIBPCAP
-  fprintf(stderr, "%s [ -vh ] [ -kQS ] [ -b <bold font> ] [ -B <byte view height> ]\n",
+  fprintf(stderr, "%s [ -vh ] [ -kpQS ] [ -B <byte view height> ] [ -c count ]\n",
          PACKAGE);
-  fprintf(stderr, "\t[ -c count ] [ -D ] [ -f <capture filter> ] [ -i interface ]\n");
-  fprintf(stderr, "\t[ -m <medium font> ] [ -n ] [ -P <packet list height> ] [ -r infile ]\n");
-  fprintf(stderr, "\t[ -R <read filter> ] [ -s snaplen ] [ -t <time stamp format> ]\n");
-  fprintf(stderr, "\t[ -T <tree view height> ] [ -w savefile ]\n");
+  fprintf(stderr, "\t[ -f <capture filter> ] [ -i interface ] [ -m <medium font> ] \n");
+  fprintf(stderr, "\t[ -n ] [ -o <preference setting> ] ... [ -P <packet list height> ]\n");
+  fprintf(stderr, "\t[ -r infile ] [ -R <read filter> ] [ -s snaplen ] \n");
+  fprintf(stderr, "\t[ -t <time stamp format> ] [ -T <tree view height> ] [ -w savefile ]\n");
 #else
-  fprintf(stderr, "%s [ -vh ] [ -b <bold font> ] [ -B <byte view height> ]\n",
+  fprintf(stderr, "%s [ -vh ] [ -B <byte view height> ] [ -m <medium font> ] [ -n ]\n",
          PACKAGE);
-  fprintf(stderr, "\t[ -m <medium font> ] [ -n ] [ -P <packet list height> ] [ -r infile ]\n");
-  fprintf(stderr, "\t[ -R <read filter> ] [ -t <time stamp format> ]\n");
+  fprintf(stderr, "\t[ -o <preference setting> ... [ -P <packet list height> ]\n");
+  fprintf(stderr, "\t[ -r infile ] [ -R <read filter> ] [ -t <time stamp format> ]\n");
   fprintf(stderr, "\t[ -T <tree view height> ]\n");
 #endif
 }
 
+static void 
+show_version(void)
+{
+#ifdef WIN32
+  create_console();
+#endif
+
+  printf("%s %s, %s\n", PACKAGE, VERSION, comp_info_str->str);
+}
+
 /* And now our feature presentation... [ fade to music ] */
 int
 main(int argc, char *argv[])
@@ -1168,32 +748,59 @@ main(int argc, char *argv[])
   int                  opt;
   extern char         *optarg;
   gboolean             arg_error = FALSE;
+
 #ifdef HAVE_LIBPCAP
 #ifdef WIN32
-  char pcap_version[] = "0.4a6";
+  char pcap_version[] = WPCAP_STRING;
 #else
   extern char          pcap_version[];
 #endif
 #endif
-  char                *pf_path;
-  int                  pf_open_errno = 0;
+  
+#ifdef WIN32
+  WSADATA             wsaData; 
+#endif
+
+  char                *gpf_path, *pf_path, *cf_path, *df_path;
+  int                  gpf_open_errno, pf_open_errno, cf_open_errno, df_open_errno;
   int                  err;
 #ifdef HAVE_LIBPCAP
   gboolean             start_capture = FALSE;
   gchar               *save_file = NULL;
   GList               *if_list;
   gchar                err_str[PCAP_ERRBUF_SIZE];
+  gboolean             stats_known;
+  struct pcap_stat     stats;
 #else
   gboolean             capture_option_specified = FALSE;
 #endif
   gint                 pl_size = 280, tv_size = 95, bv_size = 75;
   gchar               *rc_file, *cf_name = NULL, *rfilter = NULL;
-  dfilter             *rfcode = NULL;
+  dfilter_t           *rfcode = NULL;
   gboolean             rfilter_parse_failed = FALSE;
   e_prefs             *prefs;
+  char                *bold_font_name;
 
   ethereal_path = argv[0];
 
+#ifdef WIN32
+  /* Arrange that if we have no console window, and a GLib message logging
+     routine is called to log a message, we pop up a console window.
+
+     We do that by inserting our own handler for all messages logged
+     to the default domain; that handler pops up a console if necessary,
+     and then calls the default handler. */
+  g_log_set_handler(NULL,
+                   G_LOG_LEVEL_ERROR|
+                   G_LOG_LEVEL_CRITICAL|
+                   G_LOG_LEVEL_WARNING|
+                   G_LOG_LEVEL_MESSAGE|
+                   G_LOG_LEVEL_INFO|
+                   G_LOG_LEVEL_DEBUG|
+                   G_LOG_FLAG_FATAL|G_LOG_FLAG_RECURSION,
+                   console_log_handler, NULL);
+#endif
+
 #ifdef HAVE_LIBPCAP
   command_name = get_basename(ethereal_path);
   /* Set "capture_child" to indicate whether this is going to be a child
@@ -1201,6 +808,16 @@ main(int argc, char *argv[])
   capture_child = (strcmp(command_name, CHILD_NAME) == 0);
 #endif
 
+  /* Register all dissectors; we must do this before checking for the
+     "-G" flag, as the "-G" flag dumps a list of fields registered
+     by the dissectors, and we must do it before we read the preferences,
+     in case any dissectors register preferences. */
+  epan_init(PLUGIN_DIR,register_all_protocols,register_all_protocol_handoffs);
+
+  /* Now register the preferences for any non-dissector modules.
+     We must do that before we read the preferences as well. */
+  prefs_register_modules();
+
   /* If invoked with the "-G" flag, we dump out a glossary of
      display filter symbols.
 
@@ -1221,33 +838,34 @@ main(int argc, char *argv[])
 
        any arguments after the "-G" flag will not be used. */
   if (argc >= 2 && strcmp(argv[1], "-G") == 0) {
-    dissect_init();
     proto_registrar_dump();
     exit(0);
   }
 
   /* Set the current locale according to the program environment. 
    * We haven't localized anything, but some GTK widgets are localized
-   * (the file selection dialogue, for example) */
+   * (the file selection dialogue, for example).
+   * This also sets the C-language locale to the native environment. */
   gtk_set_locale();
 
   /* Let GTK get its args */
   gtk_init (&argc, &argv);
   
-  prefs = read_prefs(&pf_path);
-  if (pf_path != NULL) {
-    /* The preferences file exists, but couldn't be opened; "pf_path" is
-       its pathname.  Remember "errno", as that says why the attempt
-       failed. */
-    pf_open_errno = errno;
-  }
+  /* Read the preference files. */
+  prefs = read_prefs(&gpf_open_errno, &gpf_path, &pf_open_errno, &pf_path);
+
+  /* Read the capture filter file. */
+  read_filter_list(CFILTER_LIST, &cf_path, &cf_open_errno);
+
+  /* Read the display filter file. */
+  read_filter_list(DFILTER_LIST, &df_path, &df_open_errno);
 
   /* Initialize the capture file struct */
   cfile.plist          = NULL;
-  cfile.plist_end              = NULL;
+  cfile.plist_end      = NULL;
   cfile.wth            = NULL;
-  cfile.filename               = NULL;
-  cfile.user_saved             = FALSE;
+  cfile.filename       = NULL;
+  cfile.user_saved     = FALSE;
   cfile.is_tempfile    = FALSE;
   cfile.rfcode         = NULL;
   cfile.dfilter                = NULL;
@@ -1256,66 +874,73 @@ main(int argc, char *argv[])
   cfile.cfilter                = g_strdup(EMPTY_FILTER);
 #endif
   cfile.iface          = NULL;
-  cfile.save_file              = NULL;
+  cfile.save_file      = NULL;
   cfile.save_file_fd   = -1;
   cfile.snap           = WTAP_MAX_PACKET_SIZE;
   cfile.count          = 0;
-  cfile.cinfo.num_cols = prefs->num_cols;
-  cfile.cinfo.col_fmt      = (gint *) g_malloc(sizeof(gint) * cfile.cinfo.num_cols);
-  cfile.cinfo.fmt_matx = (gboolean **) g_malloc(sizeof(gboolean *) * cfile.cinfo.num_cols);
-  cfile.cinfo.col_width        = (gint *) g_malloc(sizeof(gint) * cfile.cinfo.num_cols);
-  cfile.cinfo.col_title    = (gchar **) g_malloc(sizeof(gchar *) * cfile.cinfo.num_cols);
-  cfile.cinfo.col_data = (gchar **) g_malloc(sizeof(gchar *) * cfile.cinfo.num_cols);
+  col_init(&cfile.cinfo, prefs->num_cols);
 
   /* Assemble the compile-time options */
-  snprintf(comp_info_str, 256,
+  comp_info_str = g_string_new("");
+
+  g_string_append(comp_info_str, "with ");
+  g_string_sprintfa(comp_info_str,
 #ifdef GTK_MAJOR_VERSION
-    "GTK+ %d.%d.%d, %s%s, %s%s, %s%s", GTK_MAJOR_VERSION, GTK_MINOR_VERSION,
-    GTK_MICRO_VERSION,
+    "GTK+ %d.%d.%d", GTK_MAJOR_VERSION, GTK_MINOR_VERSION,
+    GTK_MICRO_VERSION);
+#else
+    "GTK+ (version unknown)");
+#endif
+
+  g_string_append(comp_info_str, ", with ");
+  g_string_sprintfa(comp_info_str,
+#ifdef GLIB_MAJOR_VERSION
+    "GLib %d.%d.%d", GLIB_MAJOR_VERSION, GLIB_MINOR_VERSION,
+    GLIB_MICRO_VERSION);
 #else
-    "GTK+ (version unknown), %s%s, %s%s, %s%s",
+    "GLib (version unknown)");
 #endif
 
 #ifdef HAVE_LIBPCAP
-   "with libpcap ", pcap_version,
+  g_string_append(comp_info_str, ", with libpcap ");
+  g_string_append(comp_info_str, pcap_version);
 #else
-   "without libpcap", "",
+  g_string_append(comp_info_str, ", without libpcap");
 #endif
 
 #ifdef HAVE_LIBZ
+  g_string_append(comp_info_str, ", with libz ");
 #ifdef ZLIB_VERSION
-   "with libz ", ZLIB_VERSION,
+  g_string_append(comp_info_str, ZLIB_VERSION);
 #else /* ZLIB_VERSION */
-   "with libz ", "(version unknown)",
+  g_string_append(comp_info_str, "(version unknown)");
 #endif /* ZLIB_VERSION */
 #else /* HAVE_LIBZ */
-   "without libz", "",
+  g_string_append(comp_info_str, ", without libz");
 #endif /* HAVE_LIBZ */
 
 /* Oh, this is pretty */
 #if defined(HAVE_UCD_SNMP_SNMP_H)
+  g_string_append(comp_info_str, ", with UCD SNMP ");
 #ifdef HAVE_UCD_SNMP_VERSION_H
-   "with UCD SNMP ", VersionInfo
+  g_string_append(comp_info_str, VersionInfo);
 #else /* HAVE_UCD_SNMP_VERSION_H */
-   "with UCD SNMP ", "(version unknown)"
+  g_string_append(comp_info_str, "(version unknown)");
 #endif /* HAVE_UCD_SNMP_VERSION_H */
 #elif defined(HAVE_SNMP_SNMP_H)
+  g_string_append(comp_info_str, ", with CMU SNMP ");
 #ifdef HAVE_SNMP_VERSION_H
-   "with CMU SNMP ", snmp_Version()
+  g_string_append(comp_info_str, snmp_Version());
 #else /* HAVE_SNMP_VERSION_H */
-   "with CMU SNMP ", "(version unknown)"
+  g_string_append(comp_info_str, "(version unknown)");
 #endif /* HAVE_SNMP_VERSION_H */
 #else /* no SNMP */
-   "without SNMP", ""
+  g_string_append(comp_info_str, ", without SNMP");
 #endif
-   );
 
   /* Now get our args */
-  while ((opt = getopt(argc, argv, "b:B:c:Df:hi:km:nP:Qr:R:Ss:t:T:w:W:vZ:")) != EOF) {
+  while ((opt = getopt(argc, argv, "B:c:f:hi:km:no:pP:Qr:R:Ss:t:T:w:W:vZ:")) != EOF) {
     switch (opt) {
-      case 'b':               /* Bold font */
-       bold_font = g_strdup(optarg);
-       break;
       case 'B':        /* Byte view pane height */
         bv_size = atoi(optarg);
         break;
@@ -1327,9 +952,6 @@ main(int argc, char *argv[])
         arg_error = TRUE;
 #endif
         break;
-      case 'D':        /* Turn off DSCP printing */
-       g_ip_dscp_actif = FALSE;
-       break;
       case 'f':
 #ifdef HAVE_LIBPCAP
        if (cfile.cfilter)
@@ -1360,11 +982,36 @@ main(int argc, char *argv[])
         arg_error = TRUE;
 #endif
         break;
-      case 'm':        /* Medium font */
-       medium_font = g_strdup(optarg);
+      case 'm':        /* Fixed-width font for the display */
+        if (prefs->gui_font_name != NULL)
+          g_free(prefs->gui_font_name);
+       prefs->gui_font_name = g_strdup(optarg);
        break;
       case 'n':        /* No name resolution */
-       g_resolving_actif = 0;
+       prefs->capture_name_resolve = 0;
+       break;
+      case 'o':        /* Override preference from command line */
+        switch (prefs_set_pref(optarg)) {
+
+       case PREFS_SET_SYNTAX_ERR:
+          fprintf(stderr, "ethereal: Invalid -o flag \"%s\"\n", optarg);
+          exit(1);
+          break;
+
+        case PREFS_SET_NO_SUCH_PREF:
+          fprintf(stderr, "ethereal: -o flag \"%s\" specifies unknown preference\n",
+                       optarg);
+          exit(1);
+          break;
+        }
+        break;
+      case 'p':        /* Don't capture in promiscuous mode */
+#ifdef HAVE_LIBPCAP
+       prefs->capture_prom_mode = 0;
+#else
+        capture_option_specified = TRUE;
+        arg_error = TRUE;
+#endif
        break;
       case 'P':        /* Packet list pane height */
         pl_size = atoi(optarg);
@@ -1397,7 +1044,7 @@ main(int argc, char *argv[])
         break;
       case 'S':        /* "Sync" mode: used for following file ala tail -f */
 #ifdef HAVE_LIBPCAP
-        sync_mode = TRUE;
+        prefs->capture_auto_scroll = TRUE;
 #else
         capture_option_specified = TRUE;
         arg_error = TRUE;
@@ -1408,13 +1055,15 @@ main(int argc, char *argv[])
           timestamp_type = RELATIVE;
         else if (strcmp(optarg, "a") == 0)
           timestamp_type = ABSOLUTE;
+        else if (strcmp(optarg, "ad") == 0)
+          timestamp_type = ABSOLUTE_WITH_DATE;
         else if (strcmp(optarg, "d") == 0)
           timestamp_type = DELTA;
         else {
           fprintf(stderr, "ethereal: Invalid time stamp type \"%s\"\n",
             optarg);
           fprintf(stderr, "It must be \"r\" for relative, \"a\" for absolute,\n");
-          fprintf(stderr, "or \"d\" for delta.\n");
+          fprintf(stderr, "\"ad\" for absolute with date, or \"d\" for delta.\n");
           exit(1);
         }
         break;
@@ -1422,7 +1071,11 @@ main(int argc, char *argv[])
         tv_size = atoi(optarg);
         break;
       case 'v':        /* Show version and exit */
-        printf("%s %s, with %s\n", PACKAGE, VERSION, comp_info_str);
+        show_version();
+#ifdef WIN32
+        if (console_was_created)
+          destroy_console();
+#endif
         exit(0);
         break;
       case 'w':        /* Write to capture file xxx */
@@ -1465,6 +1118,19 @@ main(int argc, char *argv[])
     }
   }
 
+#ifdef WIN32
+  /* Load wpcap if possible */
+  load_wpcap();
+
+  /* Start windows sockets */
+  WSAStartup( MAKEWORD( 1, 1 ), &wsaData );
+#endif
+
+  /* Notify all registered modules that have had any of their preferences
+     changed either from one of the preferences file or from the command
+     line that its preferences have changed. */
+  prefs_apply_all();
+
 #ifndef HAVE_LIBPCAP
   if (capture_option_specified)
     fprintf(stderr, "This version of Ethereal was not built with support for capturing packets.\n");
@@ -1513,10 +1179,11 @@ main(int argc, char *argv[])
     cfile.cinfo.fmt_matx[i] = (gboolean *) g_malloc0(sizeof(gboolean) *
       NUM_COL_FMTS);
     get_column_format_matches(cfile.cinfo.fmt_matx[i], cfile.cinfo.col_fmt[i]);
+    cfile.cinfo.col_data[i] = NULL;
     if (cfile.cinfo.col_fmt[i] == COL_INFO)
-      cfile.cinfo.col_data[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_INFO_LEN);
+      cfile.cinfo.col_buf[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_INFO_LEN);
     else
-      cfile.cinfo.col_data[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_LEN);
+      cfile.cinfo.col_buf[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_LEN);
   }
 
   if (cfile.snap < 1)
@@ -1528,23 +1195,46 @@ main(int argc, char *argv[])
   sprintf(rc_file, "%s/%s", get_home_dir(), RC_FILE);
   gtk_rc_parse(rc_file);
 
-  if ((m_r_font = gdk_font_load(medium_font)) == NULL) {
-    fprintf(stderr, "ethereal: Error font %s not found (use -m option)\n", medium_font);
-    exit(1);
-  }
-
-  if ((m_b_font = gdk_font_load(bold_font)) == NULL) {
-    fprintf(stderr, "ethereal: Error font %s not found (use -b option)\n", bold_font);
-    exit(1);
+  /* Try to load the regular and boldface fixed-width fonts */
+  bold_font_name = boldify(prefs->gui_font_name);
+  m_r_font = gdk_font_load(prefs->gui_font_name);
+  m_b_font = gdk_font_load(bold_font_name);
+  if (m_r_font == NULL || m_b_font == NULL) {
+    /* XXX - pop this up as a dialog box? no */
+    if (m_r_font == NULL) {
+#ifdef HAVE_LIBPCAP
+      if (!capture_child)
+#endif
+       fprintf(stderr, "ethereal: Warning: font %s not found - defaulting to 6x13 and 6x13bold\n",
+               prefs->gui_font_name);
+    } else {
+      gdk_font_unref(m_r_font);
+    }
+    if (m_b_font == NULL) {
+#ifdef HAVE_LIBPCAP
+      if (!capture_child)
+#endif
+       fprintf(stderr, "ethereal: Warning: font %s not found - defaulting to 6x13 and 6x13bold\n",
+               bold_font_name);
+    } else {
+      gdk_font_unref(m_b_font);
+    }
+    g_free(bold_font_name);
+    if ((m_r_font = gdk_font_load("6x13")) == NULL) {
+      fprintf(stderr, "ethereal: Error: font 6x13 not found\n");
+      exit(1);
+    }
+    if ((m_b_font = gdk_font_load("6x13bold")) == NULL) {
+      fprintf(stderr, "ethereal: Error: font 6x13bold not found\n");
+      exit(1);
+    }
+    g_free(prefs->gui_font_name);
+    prefs->gui_font_name = g_strdup("6x13");
   }
 
-  create_main_window(pl_size, tv_size, bv_size, prefs);
-
-/* 
-   Hmmm should we do it here
-*/
+  /* Call this for the side-effects that set_fonts() produces */
+  set_fonts(m_r_font, m_b_font);
 
-  dissect_init();   /* Init anything that needs initializing */
 
 #ifdef HAVE_LIBPCAP
   /* Is this a "child" ethereal, which is only supposed to pop up a
@@ -1555,7 +1245,7 @@ main(int argc, char *argv[])
     /* No.  Pop up the main window, and read in a capture file if
        we were told to. */
 
-    gtk_widget_show(top_level);
+    create_main_window(pl_size, tv_size, bv_size, prefs);
     set_menus_for_capture_file(FALSE);
 
     cfile.colors = colfilter_new();
@@ -1568,8 +1258,8 @@ main(int argc, char *argv[])
        up on top of us. */
     if (cf_name) {
       if (rfilter != NULL) {
-        if (dfilter_compile(rfilter, &rfcode) != 0) {
-          simple_dialog(ESD_TYPE_WARN, NULL, dfilter_error_msg);
+        if (!dfilter_compile(rfilter, &rfcode)) {
+          simple_dialog(ESD_TYPE_CRIT, NULL, dfilter_error_msg);
           rfilter_parse_failed = TRUE;
         }
       }
@@ -1598,10 +1288,10 @@ main(int argc, char *argv[])
              good thing, given that "get_dirname()" does write over its
              argument. */
           s = get_dirname(cf_name);
-          if (s != NULL)
-            last_open_dir = s;
+         set_last_open_dir(s);
         } else {
-          dfilter_destroy(rfcode);
+          if (rfcode != NULL)
+            dfilter_free(rfcode);
           cfile.rfcode = NULL;
         }
       }
@@ -1610,15 +1300,44 @@ main(int argc, char *argv[])
   }
 #endif
 
-  /* If we failed to open the preferences file, pop up an alert box;
-     we defer it until now, so that the alert box is more likely to
-     come up on top of the main window. */
+  /* If the global preferences file exists but we failed to open it,
+     pop up an alert box; we defer that until now, so that the alert
+     box is more likely to come up on top of the main window. */
+  if (gpf_path != NULL) {
+      simple_dialog(ESD_TYPE_WARN, NULL,
+        "Could not open global preferences file\n\"%s\": %s.", gpf_path,
+        strerror(gpf_open_errno));
+  }
+
+  /* If the user's preferences file exists but we failed to open it,
+     pop up an alert box; we defer that until now, so that the alert
+     box is more likely to come up on top of the main window. */
   if (pf_path != NULL) {
       simple_dialog(ESD_TYPE_WARN, NULL,
-        "Could not open preferences file\n\"%s\": %s.", pf_path,
+        "Could not open your preferences file\n\"%s\": %s.", pf_path,
         strerror(pf_open_errno));
   }
 
+  /* If the user's capture filter file exists but we failed to open it,
+     pop up an alert box; we defer that until now, so that the alert
+     box is more likely to come up on top of the main window. */
+  if (cf_path != NULL) {
+      simple_dialog(ESD_TYPE_WARN, NULL,
+        "Could not open your capture filter file\n\"%s\": %s.", cf_path,
+        strerror(cf_open_errno));
+      g_free(cf_path);
+  }
+
+  /* If the user's display filter file exists but we failed to open it,
+     pop up an alert box; we defer that until now, so that the alert
+     box is more likely to come up on top of the main window. */
+  if (df_path != NULL) {
+      simple_dialog(ESD_TYPE_WARN, NULL,
+        "Could not open your display filter file\n\"%s\": %s.", df_path,
+        strerror(df_open_errno));
+      g_free(df_path);
+  }
+
 #ifdef HAVE_LIBPCAP
   if (capture_child) {
     /* This is the child process for a sync mode or fork mode capture,
@@ -1626,7 +1345,8 @@ main(int argc, char *argv[])
        a temporary file and fork off *another* child process (so don't
        call "do_capture()"). */
 
-       capture();
+       /* XXX - hand these stats to the parent process */
+       capture(&stats_known, &stats);
 
        /* The capture is done; there's nothing more for us to do. */
        gtk_exit(0);
@@ -1645,9 +1365,20 @@ main(int argc, char *argv[])
 
   gtk_main();
 
-  dissect_cleanup();
+  epan_cleanup();
   g_free(rc_file);
 
+#ifdef WIN32
+  /* Shutdown windows sockets */
+  WSACleanup();
+
+  /* For some unknown reason, the "atexit()" call in "create_console()"
+     doesn't arrange that "destroy_console()" be called when we exit,
+     so we call it here if a console was created. */
+  if (console_was_created)
+    destroy_console();
+#endif
+
   gtk_exit(0);
 
   /* This isn't reached, but we need it to keep GCC from complaining
@@ -1674,11 +1405,127 @@ WinMain (struct HINSTANCE__ *hInstance,
         char               *lpszCmdLine,
         int                 nCmdShow)
 {
+  has_no_console = TRUE;
   return main (__argc, __argv);
 }
 
+/*
+ * If this application has no console window to which its standard output
+ * would go, create one.
+ */
+static void
+create_console(void)
+{
+  if (has_no_console) {
+    /* We have no console to which to print the version string, so
+       create one and make it the standard input, output, and error. */
+    if (!AllocConsole())
+      return;   /* couldn't create console */
+    freopen("CONIN$", "r", stdin);
+    freopen("CONOUT$", "w", stdout);
+    freopen("CONOUT$", "w", stderr);
+
+    /* Well, we have a console now. */
+    has_no_console = FALSE;
+    console_was_created = TRUE;
+
+    /* Now register "destroy_console()" as a routine to be called just
+       before the application exits, so that we can destroy the console
+       after the user has typed a key (so that the console doesn't just
+       disappear out from under them, giving the user no chance to see
+       the message(s) we put in there). */
+    atexit(destroy_console);
+  }
+}
+
+static void
+destroy_console(void)
+{
+  printf("\n\nPress any key to exit\n");
+  _getch();
+  FreeConsole();
+}
+
+/* This routine should not be necessary, at least as I read the GLib
+   source code, as it looks as if GLib is, on Win32, *supposed* to
+   create a console window into which to display its output.
+
+   That doesn't happen, however.  I suspect there's something completely
+   broken about that code in GLib-for-Win32, and that it may be related
+   to the breakage that forces us to just call "printf()" on the message
+   rather than passing the message on to "g_log_default_handler()"
+   (which is the routine that does the aforementioned non-functional
+   console window creation). */
+static void
+console_log_handler(const char *log_domain, GLogLevelFlags log_level,
+                   const char *message, gpointer user_data)
+{
+  create_console();
+  if (console_was_created) {
+    /* For some unknown reason, the above doesn't appear to actually cause
+       anything to be sent to the standard output, so we'll just splat the
+       message out directly, just to make sure it gets out. */
+    printf("%s\n", message);
+  } else
+    g_log_default_handler(log_domain, log_level, message, user_data);
+}
 #endif
 
+/* Given a font name, construct the name of the next heavier version of
+   that font. */
+
+#define        XLFD_WEIGHT     3       /* index of the "weight" field */
+
+/* Map from a given weight to the appropriate weight for the "bold"
+   version of a font.
+   XXX - the XLFD says these strings shouldn't be used for font matching;
+   can we get the weight, as a number, from GDK, and ask GDK to find us
+   a font just like the given font, but with the appropriate higher
+   weight? */
+static const struct {
+       char    *light;
+       char    *heavier;
+} weight_map[] = {
+       { "ultralight", "light" },
+       { "extralight", "semilight" },
+       { "light",      "medium" },
+       { "semilight",  "semibold" },
+       { "medium",     "bold" },
+       { "normal",     "bold" },
+       { "semibold",   "extrabold" },
+       { "bold",       "ultrabold" }
+};
+#define        N_WEIGHTS       (sizeof weight_map / sizeof weight_map[0])
+       
+char *
+boldify(const char *font_name)
+{
+       char *bold_font_name;
+       gchar **xlfd_tokens;
+       int i;
+
+       /* Is this an XLFD font?  If it begins with "-", yes, otherwise no. */
+       if (font_name[0] == '-') {
+               xlfd_tokens = g_strsplit(font_name, "-", XLFD_WEIGHT+1);
+               for (i = 0; i < N_WEIGHTS; i++) {
+                       if (strcmp(xlfd_tokens[XLFD_WEIGHT],
+                           weight_map[i].light) == 0) {
+                               g_free(xlfd_tokens[XLFD_WEIGHT]);
+                               xlfd_tokens[XLFD_WEIGHT] =
+                                   g_strdup(weight_map[i].heavier);
+                               break;
+                       }
+               }
+               bold_font_name = g_strjoinv("-", xlfd_tokens);
+               g_strfreev(xlfd_tokens);
+       } else {
+               /* Append "bold" to the name of the font. */
+               bold_font_name = g_strconcat(font_name, "bold", NULL);
+       }
+       return bold_font_name;
+}
+
+
 static void
 create_main_window (gint pl_size, gint tv_size, gint bv_size, e_prefs *prefs)
 {
@@ -1687,9 +1534,16 @@ create_main_window (gint pl_size, gint tv_size, gint bv_size, e_prefs *prefs)
                       *filter_bt, *filter_cm, *filter_te,
                       *filter_reset;
   GList               *filter_list = NULL;
-  GtkStyle            *pl_style;
   GtkAccelGroup       *accel;
   int                  i;
+  /* Display filter construct dialog has an Apply button, and "OK" not
+     only sets our text widget, it activates it (i.e., it causes us to
+     filter the capture). */
+  static construct_args_t args = {
+       "Ethereal: Display Filter",
+       TRUE,
+       TRUE
+  };
 
   /* Main window */  
   top_level = gtk_window_new(GTK_WINDOW_TOPLEVEL);
@@ -1735,10 +1589,7 @@ create_main_window (gint pl_size, gint tv_size, gint bv_size, e_prefs *prefs)
   gtk_container_add(GTK_CONTAINER(pkt_scrollw), packet_list);
   
   set_plist_sel_browse(prefs->gui_plist_sel_browse);
-  pl_style = gtk_style_new();
-  gdk_font_unref(pl_style->font);
-  pl_style->font = m_r_font;
-  gtk_widget_set_style(packet_list, pl_style);
+  set_plist_font(m_r_font);
   gtk_widget_set_name(packet_list, "packet list");
   gtk_signal_connect (GTK_OBJECT (packet_list), "click_column",
     GTK_SIGNAL_FUNC(packet_list_click_column_cb), NULL);
@@ -1754,50 +1605,48 @@ create_main_window (gint pl_size, gint tv_size, gint bv_size, e_prefs *prefs)
     if (cfile.cinfo.col_fmt[i] == COL_NUMBER)
       gtk_clist_set_column_justification(GTK_CLIST(packet_list), i, 
         GTK_JUSTIFY_RIGHT);
-
-    /* Save static column sizes to use during a "-S" capture, so that
-       the columns don't resize during a live capture. */
-    cfile.cinfo.col_width[i] = gdk_string_width(pl_style->font,
-                               get_column_longest_string(get_column_format(i)));
   }
   gtk_widget_set_usize(packet_list, -1, pl_size);
-  gtk_signal_connect_object(GTK_OBJECT(packet_list), "button_press_event",
-    GTK_SIGNAL_FUNC(popup_menu_handler), gtk_object_get_data(GTK_OBJECT(popup_menu_object), PM_PACKET_LIST_KEY));
+  gtk_signal_connect(GTK_OBJECT(packet_list), "button_press_event",
+                    GTK_SIGNAL_FUNC(popup_menu_handler), 
+                    gtk_object_get_data(GTK_OBJECT(popup_menu_object), PM_PACKET_LIST_KEY));
+  gtk_signal_connect(GTK_OBJECT(packet_list), "button_press_event",
+                    GTK_SIGNAL_FUNC(packet_list_button_pressed_cb), NULL);
   gtk_clist_set_compare_func(GTK_CLIST(packet_list), packet_list_compare);
   gtk_widget_show(packet_list);
 
   /* Tree view */
+  item_style = gtk_style_new();
+  gdk_font_unref(item_style->font);
+  item_style->font = m_r_font;
   create_tree_view(tv_size, prefs, l_pane, &tv_scrollw, &tree_view,
                        prefs->gui_scrollbar_on_right);
   gtk_signal_connect(GTK_OBJECT(tree_view), "tree-select-row",
     GTK_SIGNAL_FUNC(tree_view_select_row_cb), NULL);
   gtk_signal_connect(GTK_OBJECT(tree_view), "tree-unselect-row",
     GTK_SIGNAL_FUNC(tree_view_unselect_row_cb), NULL);
-  gtk_signal_connect_object(GTK_OBJECT(tree_view), "button_press_event",
-    GTK_SIGNAL_FUNC(popup_menu_handler), gtk_object_get_data(GTK_OBJECT(popup_menu_object), PM_TREE_VIEW_KEY));
+  gtk_signal_connect(GTK_OBJECT(tree_view), "button_press_event",
+                    GTK_SIGNAL_FUNC(popup_menu_handler),
+                    gtk_object_get_data(GTK_OBJECT(popup_menu_object), PM_TREE_VIEW_KEY));
   gtk_widget_show(tree_view);
 
-  item_style = gtk_style_new();
-  gdk_font_unref(item_style->font);
-  item_style->font = m_r_font;
-
   /* Byte view. */
-  create_byte_view(bv_size, l_pane, &byte_view, &bv_scrollw,
+  create_byte_view(bv_size, l_pane, &byte_nb_ptr, &bv_scrollw,
                        prefs->gui_scrollbar_on_right);
 
-  /* Progress/filter/info box */
+  gtk_signal_connect(GTK_OBJECT(byte_nb_ptr), "button_press_event",
+                    GTK_SIGNAL_FUNC(popup_menu_handler),
+                    gtk_object_get_data(GTK_OBJECT(popup_menu_object), PM_HEXDUMP_KEY));
+
+  /* Filter/info box */
   stat_hbox = gtk_hbox_new(FALSE, 1);
   gtk_container_border_width(GTK_CONTAINER(stat_hbox), 0);
   gtk_box_pack_start(GTK_BOX(main_vbox), stat_hbox, FALSE, TRUE, 0);
   gtk_widget_show(stat_hbox);
 
-  prog_bar = gtk_progress_bar_new();
-  gtk_box_pack_start(GTK_BOX(stat_hbox), prog_bar, FALSE, TRUE, 3);
-  gtk_widget_show(prog_bar);
-
   filter_bt = gtk_button_new_with_label("Filter:");
   gtk_signal_connect(GTK_OBJECT(filter_bt), "clicked",
-    GTK_SIGNAL_FUNC(filter_browse_cb), NULL);
+    GTK_SIGNAL_FUNC(display_filter_construct_cb), &args);
   gtk_box_pack_start(GTK_BOX(stat_hbox), filter_bt, FALSE, TRUE, 0);
   gtk_widget_show(filter_bt);
   
@@ -1833,7 +1682,32 @@ create_main_window (gint pl_size, gint tv_size, gint bv_size, e_prefs *prefs)
   info_bar = gtk_statusbar_new();
   main_ctx = gtk_statusbar_get_context_id(GTK_STATUSBAR(info_bar), "main");
   file_ctx = gtk_statusbar_get_context_id(GTK_STATUSBAR(info_bar), "file");
+  help_ctx = gtk_statusbar_get_context_id(GTK_STATUSBAR(info_bar), "help");
   gtk_statusbar_push(GTK_STATUSBAR(info_bar), main_ctx, DEF_READY_MESSAGE);
   gtk_box_pack_start(GTK_BOX(stat_hbox), info_bar, TRUE, TRUE, 0);
   gtk_widget_show(info_bar);
+
+  gtk_widget_show(top_level);
+}
+
+
+void
+set_last_open_dir(char *dirname)
+{
+       int len;
+
+       if (last_open_dir) {
+               g_free(last_open_dir);
+       }
+
+       if (dirname) {
+               len = strlen(dirname);
+               if (dirname[len-1] != G_DIR_SEPARATOR) {
+                       last_open_dir = g_strconcat(dirname, G_DIR_SEPARATOR_S,
+                               NULL);
+               }
+       }
+       else {
+               last_open_dir = NULL;
+       }
 }