Ringbuffer rework.
[obnox/wireshark/wip.git] / gtk / main.c
index 64debf3e59c8e10abd087e24a02a93a72dc4f31b..a792b84e64b95d37544e6856916568d1e212a36c 100644 (file)
@@ -1,6 +1,6 @@
 /* main.c
  *
- * $Id: main.c,v 1.252 2002/05/30 00:44:50 guy Exp $
+ * $Id: main.c,v 1.298 2003/06/22 16:07:23 deniel Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@ethereal.com>
@@ -9,18 +9,18 @@
  * 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
  * as published by the Free Software Foundation; either version 2
  * of the License, or (at your option) any later version.
- * 
+ *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
@@ -41,8 +41,6 @@
 
 #include <gtk/gtk.h>
 
-#include <stdlib.h>
-#include <stdio.h>
 #include <string.h>
 #include <ctype.h>
 
 #include <unistd.h>
 #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 */
 #endif
 
-#ifdef HAVE_DIRECT_H
-#include <direct.h>
-#endif
-
-#ifdef HAVE_NETINET_IN_H
-#include <netinet/in.h>
-#endif
-
-#include <signal.h>
-
 #ifdef HAVE_LIBPCAP
 #include <pcap.h>
 #endif
 
-#ifdef HAVE_LIBZ
-#include <zlib.h>      /* to get the libz version number */
-#endif
-
 #ifdef NEED_SNPRINTF_H
 # include "snprintf.h"
 #endif
 
-#ifdef HAVE_UCD_SNMP_VERSION_H
-#include <ucd-snmp/version.h>
-#endif /* HAVE_UCD_SNMP_VERSION_H */
-
 #ifdef NEED_STRERROR_H
 #include "strerror.h"
 #endif
 #include "menu.h"
 #include "../menu.h"
 #include "color.h"
+#include "color_filters.h"
 #include "color_utils.h"
 #include "filter_prefs.h"
 #include "file_dlg.h"
 #include "ui_util.h"
 #include "image/clist_ascend.xpm"
 #include "image/clist_descend.xpm"
+#include "../tap.h"
+#include "../util.h"
+#include "compat_macros.h"
 
 #ifdef WIN32
 #include "capture-wpcap.h"
@@ -157,17 +131,23 @@ capture_file cfile;
 GtkWidget   *top_level, *packet_list, *tree_view, *byte_nb_ptr,
             *tv_scrollw, *pkt_scrollw;
 static GtkWidget       *info_bar;
+#if GTK_MAJOR_VERSION < 2
 GdkFont     *m_r_font, *m_b_font;
-guint          m_font_height, m_font_width;
+guint       m_font_height, m_font_width;
+#else
+PangoFontDescription *m_r_font, *m_b_font;
+#endif
 static guint    main_ctx, file_ctx, help_ctx;
-static GString *comp_info_str;
+static GString *comp_info_str, *runtime_info_str;
 gchar       *ethereal_path = NULL;
 gchar       *last_open_dir = NULL;
 gint   root_x = G_MAXINT, root_y = G_MAXINT, top_width, top_height;
 
 ts_type timestamp_type = RELATIVE;
 
+#if GTK_MAJOR_VERSION < 2
 GtkStyle *item_style;
+#endif
 
 /* Specifies the field currently selected in the GUI protocol tree */
 field_info *finfo_selected = NULL;
@@ -191,18 +171,23 @@ void
 about_ethereal( GtkWidget *w _U_, gpointer data _U_ ) {
   simple_dialog(ESD_TYPE_INFO, NULL,
                "Ethereal - Network Protocol Analyzer\n"
-               "Version " VERSION " (C) 1998-2000 Gerald Combs <gerald@ethereal.com>\n"
-                "Compiled %s\n\n"
+               "Version " VERSION " (C) 1998-2003 Gerald Combs <gerald@ethereal.com>\n"
+                "%s\n%s\n\n"
 
                "Check the man page for complete documentation and\n"
                "for the list of contributors.\n"
 
                "\nSee http://www.ethereal.com/ for more information.",
-                 comp_info_str->str);
+                 comp_info_str->str, runtime_info_str->str);
 }
 
+#if GTK_MAJOR_VERSION < 2
 void
 set_fonts(GdkFont *regular, GdkFont *bold)
+#else
+void
+set_fonts(PangoFontDescription *regular, PangoFontDescription *bold)
+#endif
 {
        /* Yes, assert. The code that loads the font should check
         * for NULL and provide its own error message. */
@@ -210,10 +195,31 @@ set_fonts(GdkFont *regular, GdkFont *bold)
        m_r_font = regular;
        m_b_font = bold;
 
+#if GTK_MAJOR_VERSION < 2
        m_font_height = m_r_font->ascent + m_r_font->descent;
        m_font_width = gdk_string_width(m_r_font, "0");
+#endif
 }
 
+/*
+ * Go to frame specified by currently selected protocol tree item.
+ */
+void
+goto_framenum_cb(GtkWidget *w _U_, gpointer data _U_)
+{
+    if (finfo_selected) {
+       header_field_info       *hfinfo;
+       guint32                 framenum;
+
+       hfinfo = finfo_selected->hfinfo;
+       g_assert(hfinfo);
+       if (hfinfo->type == FT_FRAMENUM) {
+           framenum = fvalue_get_integer(finfo_selected->value);
+           if (framenum != 0)
+               goto_frame(&cfile, framenum);
+       }
+    }
+}
 
 /* Match selected byte pattern */
 static void
@@ -225,7 +231,7 @@ match_selected_cb_do(gpointer data, int action, gchar *text)
     if (!text)
        return;
     g_assert(data);
-    filter_te = gtk_object_get_data(GTK_OBJECT(data), E_DFILTER_TE_KEY);
+    filter_te = OBJECT_GET_DATA(data, E_DFILTER_TE_KEY);
     g_assert(filter_te);
 
     cur_filter = gtk_editable_get_chars(GTK_EDITABLE(filter_te), 0, -1);
@@ -292,118 +298,118 @@ match_selected_cb_do(gpointer data, int action, gchar *text)
 }
 
 void
-match_selected_cb_replace(GtkWidget *w, gpointer data)
+match_selected_cb_replace_ptree(GtkWidget *w, gpointer data)
 {
     if (finfo_selected)
        match_selected_cb_do((data ? data : w),
            MATCH_SELECTED_REPLACE|MATCH_SELECTED_APPLY_NOW,
-           proto_alloc_dfilter_string(finfo_selected, cfile.pd));
+           proto_construct_dfilter_string(finfo_selected, cfile.edt));
 }
 
 void
-match_selected_cb_and(GtkWidget *w, gpointer data)
+match_selected_cb_and_ptree(GtkWidget *w, gpointer data)
 {
     if (finfo_selected)
        match_selected_cb_do((data ? data : w),
            MATCH_SELECTED_AND|MATCH_SELECTED_APPLY_NOW,
-           proto_alloc_dfilter_string(finfo_selected, cfile.pd));
+           proto_construct_dfilter_string(finfo_selected, cfile.edt));
 }
 
 void
-match_selected_cb_or(GtkWidget *w, gpointer data)
+match_selected_cb_or_ptree(GtkWidget *w, gpointer data)
 {
     if (finfo_selected)
        match_selected_cb_do((data ? data : w),
            MATCH_SELECTED_OR|MATCH_SELECTED_APPLY_NOW,
-           proto_alloc_dfilter_string(finfo_selected, cfile.pd));
+           proto_construct_dfilter_string(finfo_selected, cfile.edt));
 }
 
 void
-match_selected_cb_not(GtkWidget *w, gpointer data)
+match_selected_cb_not_ptree(GtkWidget *w, gpointer data)
 {
     if (finfo_selected)
        match_selected_cb_do((data ? data : w),
            MATCH_SELECTED_NOT|MATCH_SELECTED_APPLY_NOW,
-           proto_alloc_dfilter_string(finfo_selected, cfile.pd));
+           proto_construct_dfilter_string(finfo_selected, cfile.edt));
 }
 
 void
-match_selected_cb_and_not(GtkWidget *w, gpointer data)
+match_selected_cb_and_ptree_not(GtkWidget *w, gpointer data)
 {
     if (finfo_selected)
        match_selected_cb_do((data ? data : w),
            MATCH_SELECTED_AND_NOT|MATCH_SELECTED_APPLY_NOW,
-           proto_alloc_dfilter_string(finfo_selected, cfile.pd));
+           proto_construct_dfilter_string(finfo_selected, cfile.edt));
 }
 
 void
-match_selected_cb_or_not(GtkWidget *w, gpointer data)
+match_selected_cb_or_ptree_not(GtkWidget *w, gpointer data)
 {
     if (finfo_selected)
        match_selected_cb_do((data ? data : w),
            MATCH_SELECTED_OR_NOT,
-           proto_alloc_dfilter_string(finfo_selected, cfile.pd));
+           proto_construct_dfilter_string(finfo_selected, cfile.edt));
 }
 
 void
-prepare_selected_cb_replace(GtkWidget *w, gpointer data)
+prepare_selected_cb_replace_ptree(GtkWidget *w, gpointer data)
 {
     if (finfo_selected)
        match_selected_cb_do((data ? data : w),
            MATCH_SELECTED_REPLACE,
-           proto_alloc_dfilter_string(finfo_selected, cfile.pd));
+           proto_construct_dfilter_string(finfo_selected, cfile.edt));
 }
 
 void
-prepare_selected_cb_and(GtkWidget *w, gpointer data)
+prepare_selected_cb_and_ptree(GtkWidget *w, gpointer data)
 {
     if (finfo_selected)
        match_selected_cb_do((data ? data : w),
            MATCH_SELECTED_AND,
-           proto_alloc_dfilter_string(finfo_selected, cfile.pd));
+           proto_construct_dfilter_string(finfo_selected, cfile.edt));
 }
 
 void
-prepare_selected_cb_or(GtkWidget *w, gpointer data)
+prepare_selected_cb_or_ptree(GtkWidget *w, gpointer data)
 {
     if (finfo_selected)
        match_selected_cb_do((data ? data : w),
            MATCH_SELECTED_OR,
-           proto_alloc_dfilter_string(finfo_selected, cfile.pd));
+           proto_construct_dfilter_string(finfo_selected, cfile.edt));
 }
 
 void
-prepare_selected_cb_not(GtkWidget *w, gpointer data)
+prepare_selected_cb_not_ptree(GtkWidget *w, gpointer data)
 {
     if (finfo_selected)
        match_selected_cb_do((data ? data : w),
            MATCH_SELECTED_NOT,
-           proto_alloc_dfilter_string(finfo_selected, cfile.pd));
+           proto_construct_dfilter_string(finfo_selected, cfile.edt));
 }
 
 void
-prepare_selected_cb_and_not(GtkWidget *w, gpointer data)
+prepare_selected_cb_and_ptree_not(GtkWidget *w, gpointer data)
 {
     if (finfo_selected)
        match_selected_cb_do((data ? data : w),
            MATCH_SELECTED_AND_NOT,
-           proto_alloc_dfilter_string(finfo_selected, cfile.pd));
+           proto_construct_dfilter_string(finfo_selected, cfile.edt));
 }
 
 void
-prepare_selected_cb_or_not(GtkWidget *w, gpointer data)
+prepare_selected_cb_or_ptree_not(GtkWidget *w, gpointer data)
 {
     if (finfo_selected)
        match_selected_cb_do((data ? data : w),
            MATCH_SELECTED_OR_NOT,
-           proto_alloc_dfilter_string(finfo_selected, cfile.pd));
+           proto_construct_dfilter_string(finfo_selected, cfile.edt));
 }
 
 static gchar *
 get_text_from_packet_list(gpointer data)
 {
-    gint       row = (gint)gtk_object_get_data(GTK_OBJECT(data), E_MPACKET_LIST_ROW_KEY);
-    gint       column = (gint)gtk_object_get_data(GTK_OBJECT(data), E_MPACKET_LIST_COL_KEY);
+    gint       row = (gint)OBJECT_GET_DATA(data, E_MPACKET_LIST_ROW_KEY);
+    gint       column = (gint)OBJECT_GET_DATA(data, E_MPACKET_LIST_COL_KEY);
     frame_data *fdata = (frame_data *)gtk_clist_get_row_data(GTK_CLIST(packet_list), row);
     epan_dissect_t *edt;
     gchar      *buf=NULL;
@@ -431,12 +437,12 @@ get_text_from_packet_list(gpointer data)
 
        epan_dissect_free(edt);
     }
-           
+
     return buf;
 }
 
 void
-match_selected_cb_replace2(GtkWidget *w _U_, gpointer data)
+match_selected_cb_replace_plist(GtkWidget *w _U_, gpointer data)
 {
     match_selected_cb_do(data,
         MATCH_SELECTED_REPLACE|MATCH_SELECTED_APPLY_NOW,
@@ -444,7 +450,7 @@ match_selected_cb_replace2(GtkWidget *w _U_, gpointer data)
 }
 
 void
-match_selected_cb_and2(GtkWidget *w _U_, gpointer data)
+match_selected_cb_and_plist(GtkWidget *w _U_, gpointer data)
 {
     match_selected_cb_do(data,
         MATCH_SELECTED_AND|MATCH_SELECTED_APPLY_NOW,
@@ -452,7 +458,7 @@ match_selected_cb_and2(GtkWidget *w _U_, gpointer data)
 }
 
 void
-match_selected_cb_or2(GtkWidget *w _U_, gpointer data)
+match_selected_cb_or_plist(GtkWidget *w _U_, gpointer data)
 {
     match_selected_cb_do(data,
         MATCH_SELECTED_OR|MATCH_SELECTED_APPLY_NOW,
@@ -460,7 +466,7 @@ match_selected_cb_or2(GtkWidget *w _U_, gpointer data)
 }
 
 void
-match_selected_cb_not2(GtkWidget *w _U_, gpointer data)
+match_selected_cb_not_plist(GtkWidget *w _U_, gpointer data)
 {
     match_selected_cb_do(data,
         MATCH_SELECTED_NOT|MATCH_SELECTED_APPLY_NOW,
@@ -468,7 +474,7 @@ match_selected_cb_not2(GtkWidget *w _U_, gpointer data)
 }
 
 void
-match_selected_cb_and_not2(GtkWidget *w _U_, gpointer data)
+match_selected_cb_and_plist_not(GtkWidget *w _U_, gpointer data)
 {
     match_selected_cb_do(data,
         MATCH_SELECTED_AND_NOT|MATCH_SELECTED_APPLY_NOW,
@@ -476,7 +482,7 @@ match_selected_cb_and_not2(GtkWidget *w _U_, gpointer data)
 }
 
 void
-match_selected_cb_or_not2(GtkWidget *w _U_, gpointer data)
+match_selected_cb_or_plist_not(GtkWidget *w _U_, gpointer data)
 {
     match_selected_cb_do(data,
         MATCH_SELECTED_OR_NOT|MATCH_SELECTED_APPLY_NOW,
@@ -484,7 +490,7 @@ match_selected_cb_or_not2(GtkWidget *w _U_, gpointer data)
 }
 
 void
-prepare_selected_cb_replace2(GtkWidget *w _U_, gpointer data)
+prepare_selected_cb_replace_plist(GtkWidget *w _U_, gpointer data)
 {
     match_selected_cb_do(data,
         MATCH_SELECTED_REPLACE,
@@ -492,7 +498,7 @@ prepare_selected_cb_replace2(GtkWidget *w _U_, gpointer data)
 }
 
 void
-prepare_selected_cb_and2(GtkWidget *w _U_, gpointer data)
+prepare_selected_cb_and_plist(GtkWidget *w _U_, gpointer data)
 {
     match_selected_cb_do(data,
         MATCH_SELECTED_AND,
@@ -500,7 +506,7 @@ prepare_selected_cb_and2(GtkWidget *w _U_, gpointer data)
 }
 
 void
-prepare_selected_cb_or2(GtkWidget *w _U_, gpointer data)
+prepare_selected_cb_or_plist(GtkWidget *w _U_, gpointer data)
 {
     match_selected_cb_do(data,
         MATCH_SELECTED_OR,
@@ -508,7 +514,7 @@ prepare_selected_cb_or2(GtkWidget *w _U_, gpointer data)
 }
 
 void
-prepare_selected_cb_not2(GtkWidget *w _U_, gpointer data)
+prepare_selected_cb_not_plist(GtkWidget *w _U_, gpointer data)
 {
     match_selected_cb_do(data,
         MATCH_SELECTED_NOT,
@@ -516,7 +522,7 @@ prepare_selected_cb_not2(GtkWidget *w _U_, gpointer data)
 }
 
 void
-prepare_selected_cb_and_not2(GtkWidget *w _U_, gpointer data)
+prepare_selected_cb_and_plist_not(GtkWidget *w _U_, gpointer data)
 {
     match_selected_cb_do(data,
         MATCH_SELECTED_AND_NOT,
@@ -524,7 +530,7 @@ prepare_selected_cb_and_not2(GtkWidget *w _U_, gpointer data)
 }
 
 void
-prepare_selected_cb_or_not2(GtkWidget *w _U_, gpointer data)
+prepare_selected_cb_or_plist_not(GtkWidget *w _U_, gpointer data)
 {
     match_selected_cb_do(data,
         MATCH_SELECTED_OR_NOT,
@@ -536,16 +542,16 @@ prepare_selected_cb_or_not2(GtkWidget *w _U_, gpointer data)
 static void
 filter_activate_cb(GtkWidget *w, gpointer data)
 {
-  GtkCombo  *filter_cm = gtk_object_get_data(GTK_OBJECT(w), E_DFILTER_CM_KEY);
-  GList     *filter_list = gtk_object_get_data(GTK_OBJECT(filter_cm), E_DFILTER_FL_KEY);
+  GtkCombo  *filter_cm = OBJECT_GET_DATA(w, E_DFILTER_CM_KEY);
+  GList     *filter_list = OBJECT_GET_DATA(filter_cm, E_DFILTER_FL_KEY);
   GList     *li;
   gboolean   add_filter = TRUE;
   gboolean   free_filter = TRUE;
   char      *s;
-  
+
   g_assert(data);
   s = g_strdup(gtk_entry_get_text(GTK_ENTRY(data)));
-  
+
   /* GtkCombos don't let us get at their list contents easily, so we maintain
      our own filter list, and feed it to gtk_combo_set_popdown_strings when
      a new filter is added. */
@@ -560,7 +566,7 @@ filter_activate_cb(GtkWidget *w, gpointer data)
     if (add_filter) {
       free_filter = FALSE;
       filter_list = g_list_append(filter_list, s);
-      gtk_object_set_data(GTK_OBJECT(filter_cm), E_DFILTER_FL_KEY, filter_list);
+      OBJECT_SET_DATA(filter_cm, E_DFILTER_FL_KEY, filter_list);
       gtk_combo_set_popdown_strings(filter_cm, filter_list);
       gtk_entry_set_text(GTK_ENTRY(filter_cm->entry), g_list_last(filter_list)->data);
     }
@@ -575,7 +581,7 @@ filter_reset_cb(GtkWidget *w, gpointer data _U_)
 {
   GtkWidget *filter_te = NULL;
 
-  if ((filter_te = gtk_object_get_data(GTK_OBJECT(w), E_DFILTER_TE_KEY))) {
+  if ((filter_te = OBJECT_GET_DATA(w, E_DFILTER_TE_KEY))) {
     gtk_entry_set_text(GTK_ENTRY(filter_te), "");
   }
   filter_packets(&cfile, NULL);
@@ -586,15 +592,15 @@ static gint
 packet_list_compare(GtkCList *clist, gconstpointer  ptr1, gconstpointer  ptr2)
 {
   /* Get row text strings */
-  char *text1 = GTK_CELL_TEXT (((GtkCListRow *)ptr1)->cell[clist->sort_column])->text;
-  char *text2 = GTK_CELL_TEXT (((GtkCListRow *)ptr2)->cell[clist->sort_column])->text;
+  char *text1 = GTK_CELL_TEXT (((const GtkCListRow *)ptr1)->cell[clist->sort_column])->text;
+  char *text2 = GTK_CELL_TEXT (((const GtkCListRow *)ptr2)->cell[clist->sort_column])->text;
 
   /* Attempt to convert to numbers */
   double  num1 = atof(text1);
   double  num2 = atof(text2);
-  
+
   gint  col_fmt = cfile.cinfo.col_fmt[clist->sort_column];
-  
+
   if ((col_fmt == COL_NUMBER) || (col_fmt == COL_REL_TIME) || (col_fmt == COL_DELTA_TIME) ||
       ((col_fmt == COL_CLS_TIME) && (timestamp_type == RELATIVE)) ||
       ((col_fmt == COL_CLS_TIME) && (timestamp_type == DELTA))    ||
@@ -612,9 +618,9 @@ packet_list_compare(GtkCList *clist, gconstpointer  ptr1, gconstpointer  ptr2)
     else
       return 0;
   }
-  
+
   else {
-    
+
     /* Compare text column */
     if (!text2)
       return (text1 != NULL);
@@ -627,19 +633,19 @@ packet_list_compare(GtkCList *clist, gconstpointer  ptr1, gconstpointer  ptr2)
 }
 
 /* What to do when a column is clicked */
-static void 
+static void
 packet_list_click_column_cb(GtkCList *clist, gint column, gpointer data)
 {
   column_arrows *col_arrows = (column_arrows *) data;
   int i;
-  
+
   gtk_clist_freeze(clist);
-  
+
   for (i = 0; i < cfile.cinfo.num_cols; i++) {
     gtk_widget_hide(col_arrows[i].ascend_pm);
     gtk_widget_hide(col_arrows[i].descend_pm);
   }
-  
+
   if (column == clist->sort_column) {
     if (clist->sort_type == GTK_SORT_ASCENDING) {
       clist->sort_type = GTK_SORT_DESCENDING;
@@ -660,7 +666,7 @@ packet_list_click_column_cb(GtkCList *clist, gint column, gpointer data)
 }
 
 /* mark packets */
-static void 
+static void
 set_frame_mark(gboolean set, frame_data *frame, gint row) {
   GdkColor fg, bg;
 
@@ -670,39 +676,68 @@ set_frame_mark(gboolean set, frame_data *frame, gint row) {
     mark_frame(&cfile, frame);
     color_t_to_gdkcolor(&fg, &prefs.gui_marked_fg);
     color_t_to_gdkcolor(&bg, &prefs.gui_marked_bg);
+    gtk_clist_set_background(GTK_CLIST(packet_list), row, &bg);
+    gtk_clist_set_foreground(GTK_CLIST(packet_list), row, &fg);
   } else {
     unmark_frame(&cfile, frame);
-    fg = BLACK;
-    bg = WHITE;
+    gtk_clist_set_background(GTK_CLIST(packet_list), row, NULL);
+    gtk_clist_set_foreground(GTK_CLIST(packet_list), row, NULL);
   }
   file_set_save_marked_sensitive();
-  gtk_clist_set_background(GTK_CLIST(packet_list), row, &bg);
-  gtk_clist_set_foreground(GTK_CLIST(packet_list), row, &fg);
 }
 
+#if GTK_MAJOR_VERSION < 2
 static void
-packet_list_button_pressed_cb(GtkWidget *w, GdkEvent *event, gpointer data _U_) {
-  
-  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);
-  }
+packet_list_button_pressed_cb(GtkWidget *w, GdkEvent *event, gpointer data _U_)
+{
+    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);
+    }
 }
+#else
+static gint
+packet_list_button_pressed_cb(GtkWidget *w, GdkEvent *event, gpointer data _U_)
+{
+    GdkEventButton *event_button = (GdkEventButton *)event;
+    gint row, column;
+
+    if (w == NULL || event == NULL)
+        return FALSE;
+
+    if (event->type == GDK_BUTTON_PRESS &&
+        gtk_clist_get_selection_info(GTK_CLIST(w), event_button->x,
+                                     event_button->y, &row, &column)) {
+        if (event_button->button == 2)
+        {
+            frame_data *fdata = (frame_data *)gtk_clist_get_row_data(GTK_CLIST(w), row);
+            set_frame_mark(!fdata->flags.marked, fdata, row);
+            return TRUE;
+        }
+        else if (event_button->button == 1) {
+            gtk_clist_select_row(GTK_CLIST(w), row, column);
+            return TRUE;
+        }
+    }
+    return FALSE;
+}
+#endif
 
 void mark_frame_cb(GtkWidget *w _U_, gpointer data _U_) {
   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,
+                  gtk_clist_find_row_from_data(GTK_CLIST(packet_list),
                                                cfile.current_frame));
   }
 }
@@ -712,7 +747,7 @@ static void mark_all_frames(gboolean set) {
   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));    
+                  gtk_clist_find_row_from_data(GTK_CLIST(packet_list), fdata));
   }
 }
 
@@ -755,80 +790,130 @@ packet_list_unselect_cb(GtkWidget *w _U_, gint row _U_, gint col _U_, gpointer e
 }
 
 
+#if GTK_MAJOR_VERSION < 2
 static void
-tree_view_select_row_cb(GtkCTree *ctree, GList *node, gint column _U_, gpointer user_data _U_)
+tree_view_select_row_cb(GtkCTree *ctree, GList *node, gint column _U_,
+                        gpointer user_data _U_)
+#else
+static void
+tree_view_selection_changed_cb(GtkTreeSelection *sel, gpointer user_data _U_)
+#endif
 {
-       field_info      *finfo;
-       gchar           *help_str = NULL;
-       gboolean        has_blurb = FALSE;
-       guint           length = 0, byte_len;
-       GtkWidget       *byte_view;
-       const guint8    *byte_data;
+    field_info   *finfo;
+    gchar        *help_str = NULL;
+    gchar         len_str[2+10+1+5+1]; /* ", {N} bytes\0",
+                                          N < 4294967296 */
+    gboolean      has_blurb = FALSE;
+    guint         length = 0, byte_len;
+    GtkWidget    *byte_view;
+    const guint8 *byte_data;
+#if GTK_MAJOR_VERSION >= 2
+    GtkTreeModel *model;
+    GtkTreeIter   iter;
+#endif
+
+#if GTK_MAJOR_VERSION >= 2
+    /* if nothing is selected */
+    if (!gtk_tree_selection_get_selected(sel, &model, &iter))
+    {
+        /*
+         * Which byte view is displaying the current protocol tree
+         * row's data?
+         */
+        byte_view = get_notebook_bv_ptr(byte_nb_ptr);
+        if (byte_view == NULL)
+            return;    /* none */
+
+        byte_data = get_byte_view_data_and_length(byte_view, &byte_len);
+        if (byte_data == NULL)
+            return;    /* none */
+
+        unselect_field();
+        packet_hex_print(GTK_TEXT_VIEW(byte_view), byte_data,
+                         cfile.current_frame, NULL, byte_len);
+        return;
+    }
+    gtk_tree_model_get(model, &iter, 1, &finfo, -1);
+#else
+    g_assert(node);
+    finfo = gtk_ctree_node_get_row_data( ctree, GTK_CTREE_NODE(node) );
+#endif
+    if (!finfo) return;
 
-       g_assert(node);
-       finfo = gtk_ctree_node_get_row_data( ctree, GTK_CTREE_NODE(node) );
-       if (!finfo) return;
+    set_notebook_page(byte_nb_ptr, finfo->ds_tvb);
 
-       set_notebook_page(byte_nb_ptr, finfo->ds_tvb);
+    byte_view = get_notebook_bv_ptr(byte_nb_ptr);
+    byte_data = get_byte_view_data_and_length(byte_view, &byte_len);
+    g_assert(byte_data != NULL);
 
-       byte_view = get_notebook_bv_ptr(byte_nb_ptr);
-       byte_data = get_byte_view_data_and_length(byte_view, &byte_len);
-       g_assert(byte_data != NULL);
-
-       finfo_selected = finfo;
-       set_menus_for_selected_tree_row(TRUE);
-
-       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);
-         }
-         statusbar_pop_field_msg();    /* get rid of current help msg */
-          if (length) {
-           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);
-           statusbar_push_field_msg(help_str);
-           g_free(help_str);
-          } else {
+    finfo_selected = finfo;
+    set_menus_for_selected_tree_row(TRUE);
+
+    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);
+        }
+        if (finfo->length == 0) {
+            len_str[0] = '\0';
+        } else if (finfo->length == 1) {
+            strcpy (len_str, ", 1 byte");
+        } else {
+            snprintf (len_str, sizeof len_str, ", %d bytes", finfo->length);
+        }
+        statusbar_pop_field_msg();     /* get rid of current help msg */
+        if (length) {
+            length += strlen(finfo->hfinfo->abbrev) + strlen(len_str) + 10;
+            help_str = g_malloc(sizeof(gchar) * length);
+            sprintf(help_str, "%s (%s)%s",
+                    (has_blurb) ? finfo->hfinfo->blurb : finfo->hfinfo->name,
+                    finfo->hfinfo->abbrev, len_str);
+            statusbar_push_field_msg(help_str);
+            g_free(help_str);
+        } else {
             /*
-            * Don't show anything if the field name is zero-length;
-            * the pseudo-field for "proto_tree_add_text()" is such
-            * a field, and we don't want "Text (text)" showing up
-            * on the status line if you've selected such a field.
-            *
-            * XXX - there are zero-length fields for which we *do*
-            * want to show the field name.
-            *
-            * XXX - perhaps the name and abbrev field should be null
-            * pointers rather than null strings for that pseudo-field,
-            * but we'd have to add checks for null pointers in some
-            * places if we did that.
-            *
-            * Or perhaps protocol tree items added with
-            * "proto_tree_add_text()" should have -1 as the field index,
-            * with no pseudo-field being used, but that might also
-            * require special checks for -1 to be added.
-            */
-           statusbar_push_field_msg("");
-          }
-       }
+             * Don't show anything if the field name is zero-length;
+             * the pseudo-field for "proto_tree_add_text()" is such
+             * a field, and we don't want "Text (text)" showing up
+             * on the status line if you've selected such a field.
+             *
+             * XXX - there are zero-length fields for which we *do*
+             * want to show the field name.
+             *
+             * XXX - perhaps the name and abbrev field should be null
+             * pointers rather than null strings for that pseudo-field,
+             * but we'd have to add checks for null pointers in some
+             * places if we did that.
+             *
+             * Or perhaps protocol tree items added with
+             * "proto_tree_add_text()" should have -1 as the field index,
+             * with no pseudo-field being used, but that might also
+             * require special checks for -1 to be added.
+             */
+            statusbar_push_field_msg("");
+        }
+    }
 
-       packet_hex_print(GTK_TEXT(byte_view), byte_data, cfile.current_frame,
-               finfo, byte_len);
+#if GTK_MAJOR_VERSION < 2
+    packet_hex_print(GTK_TEXT(byte_view), byte_data, cfile.current_frame,
+                     finfo, byte_len);
+#else
+    packet_hex_print(GTK_TEXT_VIEW(byte_view), byte_data, cfile.current_frame,
+                     finfo, byte_len);
+#endif
 }
 
+#if GTK_MAJOR_VERSION < 2
 static void
-tree_view_unselect_row_cb(GtkCTree *ctree _U_, GList *node _U_, gint column _U_, gpointer user_data _U_)
+tree_view_unselect_row_cb(GtkCTree *ctree _U_, GList *node _U_, gint column _U_,
+                          gpointer user_data _U_)
 {
        GtkWidget       *byte_view;
        const guint8    *data;
-       guint           len;    
+       guint           len;
 
        /*
         * Which byte view is displaying the current protocol tree
@@ -846,6 +931,7 @@ tree_view_unselect_row_cb(GtkCTree *ctree _U_, GList *node _U_, gint column _U_,
        packet_hex_print(GTK_TEXT(byte_view), data, cfile.current_frame,
                NULL, len);
 }
+#endif
 
 void collapse_all_cb(GtkWidget *widget _U_, gpointer data _U_) {
   if (cfile.edt->tree)
@@ -905,13 +991,19 @@ set_plist_sel_browse(gboolean val)
                gtk_clist_set_selection_mode(GTK_CLIST(packet_list), GTK_SELECTION_BROWSE);
        }
 }
-       
+
 /* Set the font of the packet list window. */
+#if GTK_MAJOR_VERSION < 2
 void
 set_plist_font(GdkFont *font)
+#else
+void
+set_plist_font(PangoFontDescription *font)
+#endif
 {
-       GtkStyle *style;
        int i;
+#if GTK_MAJOR_VERSION < 2
+       GtkStyle *style;
 
        style = gtk_style_new();
        gdk_font_unref(style->font);
@@ -919,12 +1011,25 @@ set_plist_font(GdkFont *font)
        gdk_font_ref(font);
 
        gtk_widget_set_style(packet_list, style);
+#else
+        PangoLayout *layout;
+
+        gtk_widget_modify_font(packet_list, font);
+#endif
 
        /* 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++) {
+#if GTK_MAJOR_VERSION < 2
                cfile.cinfo.col_width[i] = gdk_string_width(font,
                        get_column_longest_string(get_column_format(i)));
+#else
+                layout = gtk_widget_create_pango_layout(packet_list,
+                   get_column_longest_string(get_column_format(i)));
+                pango_layout_get_pixel_size(layout, &cfile.cinfo.col_width[i],
+                                            NULL);
+                g_object_unref(G_OBJECT(layout));
+#endif
        }
 }
 
@@ -1065,45 +1170,45 @@ file_quit_cmd_cb (GtkWidget *widget _U_, gpointer data _U_)
        do_quit();
 }
 
-static void 
+static void
 print_usage(gboolean print_ver) {
 
   if (print_ver) {
-    fprintf(stderr, "This is GNU " PACKAGE " " VERSION ", compiled %s\n",
-         comp_info_str->str);
-  }  
+    fprintf(stderr, "This is GNU " PACKAGE " " VERSION "\n%s\n%s\n",
+         comp_info_str->str, runtime_info_str->str);
+  }
 #ifdef HAVE_LIBPCAP
-  fprintf(stderr, "\n%s [ -vh ] [ -klpQS ] [ -a <capture autostop condition> ] ...\n",
+  fprintf(stderr, "\n%s [ -vh ] [ -klnpQS ] [ -a <capture autostop condition> ] ...\n",
          PACKAGE);
-  fprintf(stderr, "\t[ -b <number of ringbuffer files> ] [ -B <byte view height> ]\n");
-  fprintf(stderr, "\t[ -c <count> ] [ -f <capture filter> ] [ -i <interface> ]\n");
-  fprintf(stderr, "\t[ -m <medium font> ] [ -n ] [ -N <resolving> ]\n");
+  fprintf(stderr, "\t[ -b <number of ringbuffer files>[:<duration>] ]\n");
+  fprintf(stderr, "\t[ -B <byte view height> ] [ -c <count> ] [ -f <capture filter> ]\n");
+  fprintf(stderr, "\t[ -i <interface> ] [ -m <medium font> ] [ -N <resolving> ]\n");
   fprintf(stderr, "\t[ -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> ]\n");
   fprintf(stderr, "\t[ -w <savefile> ] [ <infile> ]\n");
 #else
-  fprintf(stderr, "\n%s [ -vh ] [ -B <byte view height> ] [ -m <medium font> ]\n",
+  fprintf(stderr, "\n%s [ -vh ] [ -n ] [ -B <byte view height> ] [ -m <medium font> ]\n",
          PACKAGE);
-  fprintf(stderr, "\t[ -n ] [ -N <resolving> ]\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> ] [ <infile> ]\n");
+  fprintf(stderr, "\t[ -N <resolving> ] [ -o <preference setting> ...\n");
+  fprintf(stderr, "\t[ -P <packet list height> ] [ -r <infile> ] [ -R <read filter> ]\n");
+  fprintf(stderr, "\t[ -t <time stamp format> ] [ -T <tree view height> ] [ <infile> ]\n");
 #endif
 }
 
-static void 
+static void
 show_version(void)
 {
 #ifdef WIN32
   create_console();
 #endif
 
-  printf("%s %s, %s\n", PACKAGE, VERSION, comp_info_str->str);
+  printf("%s %s\n%s\n%s\n", PACKAGE, VERSION, comp_info_str->str,
+         runtime_info_str->str);
 }
 
 static int
-get_positive_int(const char *string, const char *name)
+get_natural_int(const char *string, const char *name)
 {
   long number;
   char *p;
@@ -1119,11 +1224,6 @@ get_positive_int(const char *string, const char *name)
            name, string);
     exit(1);
   }
-  if (number == 0) {
-    fprintf(stderr, "ethereal: The specified %s \"%s\" is zero\n",
-            name, string);
-    exit(1);
-  }
   if (number > INT_MAX) {
     fprintf(stderr, "ethereal: The specified %s \"%s\" is too large (greater than %d)\n",
            name, string, INT_MAX);
@@ -1132,6 +1232,22 @@ get_positive_int(const char *string, const char *name)
   return number;
 }
 
+static int
+get_positive_int(const char *string, const char *name)
+{
+  long number;
+
+  number = get_natural_int(string, name);
+
+  if (number == 0) {
+    fprintf(stderr, "ethereal: The specified %s is zero\n",
+           name);
+    exit(1);
+  }
+
+  return number;
+}
+
 #ifdef HAVE_LIBPCAP
 /*
  * Given a string of the form "<autostop criterion>:<value>", as might appear
@@ -1142,7 +1258,7 @@ get_positive_int(const char *string, const char *name)
 static gboolean
 set_autostop_criterion(const char *autostoparg)
 {
-  u_char *p, *colonp;
+  guchar *p, *colonp;
 
   colonp = strchr(autostoparg, ':');
   if (colonp == NULL)
@@ -1179,7 +1295,137 @@ set_autostop_criterion(const char *autostoparg)
   *colonp = ':'; /* put the colon back */
   return TRUE;
 }
+
+/*
+ * Given a string of the form "<ring buffer file>:<duration>", as might appear
+ * as an argument to a "-b" option, parse it and set the arguments in
+ * question.  Return an indication of whether it succeeded or failed
+ * in some fashion.
+ */
+static gboolean
+get_ring_arguments(const char *arg)
+{
+  guchar *p = NULL, *colonp;
+
+  colonp = strchr(arg, ':');
+
+  if (colonp != NULL) {
+    p = colonp;
+    *p++ = '\0';
+  }
+
+  capture_opts.ringbuffer_num_files = 
+    get_natural_int(arg, "number of ring buffer files");
+
+  if (colonp == NULL)
+    return TRUE;
+
+  /*
+   * Skip over any white space (there probably won't be any, but
+   * as we allow it in the preferences file, we might as well
+   * allow it here).
+   */
+  while (isspace(*p))
+    p++;
+  if (*p == '\0') {
+    /*
+     * Put the colon back, so if our caller uses, in an
+     * error message, the string they passed us, the message
+     * looks correct.
+     */
+    *colonp = ':';
+    return FALSE;
+  }
+
+  capture_opts.has_ring_duration = TRUE;
+  capture_opts.ringbuffer_duration = get_positive_int(p,
+                                                     "ring buffer duration");
+
+  *colonp = ':';       /* put the colon back */
+  return TRUE;
+}
+#endif
+
+#if defined WIN32 || GTK_MAJOR_VERSION < 2 || ! defined USE_THREADS
+/* 
+   Once every 3 seconds we get a callback here which we use to update
+   the tap extensions. Since Gtk1 is single threaded we dont have to
+   worry about any locking or critical regions.
+ */
+static gint
+update_cb(gpointer data _U_)
+{
+       draw_tap_listeners(FALSE);
+       return 1;
+}
+#else
+
+/* if these three functions are copied to gtk1 ethereal, since gtk1 does not
+   use threads all updte_thread_mutex can be dropped and protect/unprotect 
+   would just be empty functions.
+
+   This allows gtk2-rpcstat.c and friends to be copied unmodified to 
+   gtk1-ethereal and it will just work.
+ */
+static GStaticMutex update_thread_mutex = G_STATIC_MUTEX_INIT;
+gpointer
+update_thread(gpointer data _U_)
+{
+    while(1){
+        GTimeVal tv1, tv2;
+        g_get_current_time(&tv1);
+        g_static_mutex_lock(&update_thread_mutex);
+        gdk_threads_enter();
+        draw_tap_listeners(FALSE);
+        gdk_threads_leave();
+        g_static_mutex_unlock(&update_thread_mutex);
+        g_thread_yield();
+        g_get_current_time(&tv2);
+        if( ((tv1.tv_sec + 2) * 1000000 + tv1.tv_usec) >
+            (tv2.tv_sec * 1000000 + tv2.tv_usec) ){
+            g_usleep(((tv1.tv_sec + 2) * 1000000 + tv1.tv_usec) -
+                     (tv2.tv_sec * 1000000 + tv2.tv_usec));
+        }
+    }
+    return NULL;
+}
+#endif
+void
+protect_thread_critical_region(void)
+{
+#if ! defined WIN32 && GTK_MAJOR_VERSION >= 2 && defined USE_THREADS
+    g_static_mutex_lock(&update_thread_mutex);
+#endif
+}
+void
+unprotect_thread_critical_region(void)
+{
+#if ! defined WIN32 && GTK_MAJOR_VERSION >= 2 && defined USE_THREADS
+    g_static_mutex_unlock(&update_thread_mutex);
 #endif
+}
+
+/* structure to keep track of what tap listeners have been registered.
+ */
+typedef struct _ethereal_tap_list {
+       struct _ethereal_tap_list *next;
+       char *cmd;
+       void (*func)(char *arg);
+} ethereal_tap_list;
+static ethereal_tap_list *tap_list=NULL;
+
+void
+register_ethereal_tap(char *cmd, void (*func)(char *arg))
+{
+       ethereal_tap_list *newtl;
+
+       newtl=malloc(sizeof(ethereal_tap_list));
+       newtl->next=tap_list;
+       tap_list=newtl;
+       newtl->cmd=cmd;
+       newtl->func=func;
+
+}
 
 /* And now our feature presentation... [ fade to music ] */
 int
@@ -1193,18 +1439,13 @@ main(int argc, char *argv[])
   int                  opt;
   extern char         *optarg;
   gboolean             arg_error = FALSE;
-#ifdef HAVE_LIBPCAP
-#ifdef HAVE_PCAP_VERSION
-  extern char          pcap_version[];
-#endif /* HAVE_PCAP_VERSION */
-#endif /* HAVE_LIBPCAP */
-  
+
 #ifdef WIN32
-  WSADATA             wsaData; 
-#endif
+  WSADATA             wsaData;
+#endif  /* WIN32 */
 
   char                *gpf_path, *cf_path, *df_path;
-  const char          *pf_path;
+  char                *pf_path;
   int                  gpf_open_errno, pf_open_errno, cf_open_errno, df_open_errno;
   int                  err;
 #ifdef HAVE_LIBPCAP
@@ -1223,11 +1464,15 @@ main(int argc, char *argv[])
   gboolean             rfilter_parse_failed = FALSE;
   e_prefs             *prefs;
   char                 badopt;
+#if GTK_MAJOR_VERSION < 2
   char                *bold_font_name;
+#endif
   gint                 desk_x, desk_y;
   gboolean             prefs_write_needed = FALSE;
+  ethereal_tap_list   *tli = NULL;
+  gchar               *tap_opt = NULL;
 
-#define OPTSTRING_INIT "a:b:B:c:f:hi:klm:nN:o:pP:Qr:R:Ss:t:T:w:v"
+#define OPTSTRING_INIT "a:b:B:c:f:hi:klm:nN:o:pP:Qr:R:Ss:t:T:w:vz:"
 
 #ifdef HAVE_LIBPCAP
 #ifdef WIN32
@@ -1277,6 +1522,10 @@ main(int argc, char *argv[])
      case any dissectors register preferences. */
   epan_init(PLUGIN_DIR,register_all_protocols,register_all_protocol_handoffs);
 
+  /* Register all tap listeners; we do this before we parse the arguments,
+     as the "-z" argument can specify a registered tap. */
+  register_all_tap_listeners();
+
   /* Now register the preferences for any non-dissector modules.
      We must do that before we read the preferences as well. */
   prefs_register_modules();
@@ -1314,7 +1563,7 @@ main(int argc, char *argv[])
       else if (strcmp(argv[2], "protocols") == 0)
         proto_registrar_dump_protocols();
       else {
-        fprintf(stderr, "tethereal: Invalid \"%s\" option for -G flag\n",
+        fprintf(stderr, "ethereal: Invalid \"%s\" option for -G flag\n",
                 argv[2]);
         exit(1);
       }
@@ -1322,7 +1571,26 @@ main(int argc, char *argv[])
     exit(0);
   }
 
-  /* Set the current locale according to the program environment. 
+  /* multithread support currently doesn't seem to work in win32 gtk2.0.6 */
+#if ! defined WIN32 && GTK_MAJOR_VERSION >= 2 && defined G_THREADS_ENABLED && defined USE_THREADS
+  {
+      GThread *ut;
+      g_thread_init(NULL);
+      gdk_threads_init();
+      ut=g_thread_create(update_thread, NULL, FALSE, NULL);
+      g_thread_set_priority(ut, G_THREAD_PRIORITY_LOW);
+  }
+#else  /* WIN32 || GTK1.2 || !G_THREADS_ENABLED || !USE_THREADS */
+  /* this is to keep tap extensions updating once every 3 seconds */
+  gtk_timeout_add(3000, (GtkFunction)update_cb,(gpointer)NULL);
+#endif /* !WIN32 && GTK2 && G_THREADS_ENABLED */
+
+#if HAVE_GNU_ADNS
+  gtk_timeout_add(750, (GtkFunction) host_name_lookup_process, NULL);
+#endif
+
+
+  /* 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).
    * This also sets the C-language locale to the native environment. */
@@ -1330,7 +1598,7 @@ main(int argc, char *argv[])
 
   /* Let GTK get its args */
   gtk_init (&argc, &argv);
-  
+
   /* Read the preference files. */
   prefs = read_prefs(&gpf_open_errno, &gpf_path, &pf_open_errno, &pf_path);
 
@@ -1345,6 +1613,8 @@ main(int argc, char *argv[])
   capture_opts.autostop_filesize = 1;
   capture_opts.ringbuffer_on = FALSE;
   capture_opts.ringbuffer_num_files = RINGBUFFER_MIN_NUM_FILES;
+  capture_opts.has_ring_duration = FALSE;
+  capture_opts.ringbuffer_duration = 1;
 
   /* If this is a capture child process, it should pay no attention
      to the "prefs.capture_prom_mode" setting in the preferences file;
@@ -1375,81 +1645,25 @@ main(int argc, char *argv[])
   /* 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.wth            = NULL;
-  cfile.filename       = NULL;
-  cfile.user_saved     = FALSE;
-  cfile.is_tempfile    = FALSE;
-  cfile.rfcode         = NULL;
-  cfile.dfilter                = NULL;
-  cfile.dfcode         = NULL;
-#ifdef HAVE_LIBPCAP
-  cfile.cfilter                = g_strdup(EMPTY_FILTER);
-#endif
-  cfile.iface          = NULL;
-  cfile.save_file      = NULL;
-  cfile.save_file_fd   = -1;
-  cfile.has_snap       = FALSE;
-  cfile.snap           = WTAP_MAX_PACKET_SIZE;
-  cfile.count          = 0;
-  col_init(&cfile.cinfo, prefs->num_cols);
-
-  /* Assemble the compile-time options */
-  comp_info_str = g_string_new("");
+  init_cap_file(&cfile);
 
+  /* Assemble the compile-time version information string */
+  comp_info_str = g_string_new("Compiled ");
   g_string_append(comp_info_str, "with ");
   g_string_sprintfa(comp_info_str,
 #ifdef GTK_MAJOR_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);
+                    "GTK+ %d.%d.%d", GTK_MAJOR_VERSION, GTK_MINOR_VERSION,
+                    GTK_MICRO_VERSION);
 #else
-    "GLib (version unknown)");
+                    "GTK+ (version unknown)");
 #endif
 
-#ifdef HAVE_LIBPCAP
-  g_string_append(comp_info_str, ", with libpcap ");
-#ifdef HAVE_PCAP_VERSION
-  g_string_append(comp_info_str, pcap_version);
-#else /* HAVE_PCAP_VERSION */
-  g_string_append(comp_info_str, "(version unknown)");
-#endif /* HAVE_PCAP_VERSION */
-#else /* HAVE_LIBPCAP */
-  g_string_append(comp_info_str, ", without libpcap");
-#endif /* HAVE_LIBPCAP */
+  g_string_append(comp_info_str, ", ");
+  get_compiled_version_info(comp_info_str);
 
-#ifdef HAVE_LIBZ
-  g_string_append(comp_info_str, ", with libz ");
-#ifdef ZLIB_VERSION
-  g_string_append(comp_info_str, ZLIB_VERSION);
-#else /* ZLIB_VERSION */
-  g_string_append(comp_info_str, "(version unknown)");
-#endif /* ZLIB_VERSION */
-#else /* HAVE_LIBZ */
-  g_string_append(comp_info_str, ", without libz");
-#endif /* HAVE_LIBZ */
-
-/* Oh, this is pretty */
-#ifdef HAVE_UCD_SNMP
-  g_string_append(comp_info_str, ", with UCD SNMP ");
-#ifdef HAVE_UCD_SNMP_VERSION_H
-  g_string_append(comp_info_str, VersionInfo);
-#else /* HAVE_UCD_SNMP_VERSION_H */
-  g_string_append(comp_info_str, "(version unknown)");
-#endif /* HAVE_UCD_SNMP_VERSION_H */
-#else /* no SNMP library */
-  g_string_append(comp_info_str, ", without UCD SNMP");
-#endif
+  /* Assemble the run-time version information string */
+  runtime_info_str = g_string_new("Running ");
+  get_runtime_version_info(runtime_info_str);
 
   /* Now get our args */
   while ((opt = getopt(argc, argv, optstring)) != -1) {
@@ -1458,7 +1672,7 @@ main(int argc, char *argv[])
 #ifdef HAVE_LIBPCAP
         if (set_autostop_criterion(optarg) == FALSE) {
           fprintf(stderr, "ethereal: Invalid or unknown -a flag \"%s\"\n", optarg);
-          exit(1);          
+          exit(1);
         }
 #else
         capture_option_specified = TRUE;
@@ -1468,8 +1682,10 @@ main(int argc, char *argv[])
       case 'b':        /* Ringbuffer option */
 #ifdef HAVE_LIBPCAP
         capture_opts.ringbuffer_on = TRUE;
-        capture_opts.ringbuffer_num_files =
-          get_positive_int(optarg, "number of ring buffer files");
+       if (get_ring_arguments(optarg) == FALSE) {
+          fprintf(stderr, "ethereal: Invalid or unknown -b arg \"%s\"\n", optarg);
+          exit(1);
+       }
 #else
         capture_option_specified = TRUE;
         arg_error = TRUE;
@@ -1649,6 +1865,22 @@ main(int argc, char *argv[])
         cfile.save_file_fd = atoi(optarg);
        break;
 #endif
+      case 'z':
+        for(tli=tap_list;tli;tli=tli->next){
+          if(!strncmp(tli->cmd,optarg,strlen(tli->cmd))){
+            tap_opt = g_strdup(optarg);
+            break;
+          }
+        }
+        if(!tli){
+          fprintf(stderr,"ethereal: invalid -z argument.\n");
+          fprintf(stderr,"  -z argument must be one of :\n");
+          for(tli=tap_list;tli;tli=tli->next){
+            fprintf(stderr,"     %s\n",tli->cmd);
+          }
+          exit(1);
+        }
+        break;
 
 #ifdef _WIN32
 #ifdef HAVE_LIBPCAP
@@ -1716,7 +1948,7 @@ main(int argc, char *argv[])
           sync_mode takes precedence;
        c) it makes no sense to enable the ring buffer if the maximum
           file size is set to "infinite". */
-    if (cfile.save_file == NULL) {
+    if (save_file == NULL) {
       fprintf(stderr, "ethereal: Ring buffer requested, but capture isn't being saved to a permanent file.\n");
       capture_opts.ringbuffer_on = FALSE;
     }
@@ -1737,11 +1969,11 @@ main(int argc, char *argv[])
 
   /* Start windows sockets */
   WSAStartup( MAKEWORD( 1, 1 ), &wsaData );
-#endif
+#endif  /* WIN32 */
 
   /* 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. */
+     line that their preferences have changed. */
   prefs_apply_all();
 
 #ifndef HAVE_LIBPCAP
@@ -1762,12 +1994,12 @@ main(int argc, char *argv[])
         if_list = get_interface_list(&err, err_str);
         if (if_list == NULL) {
           switch (err) {
-  
+
           case CANT_GET_INTERFACE_LIST:
               fprintf(stderr, "ethereal: Can't get list of interfaces: %s\n",
                        err_str);
               break;
-  
+
           case NO_INTERFACES_FOUND:
               fprintf(stderr, "ethereal: There are no interfaces on which a capture can be done\n");
               break;
@@ -1789,7 +2021,8 @@ main(int argc, char *argv[])
   }
 #endif
 
-  /* Build the column format array */  
+  /* Build the column format array */
+  col_setup(&cfile.cinfo, prefs->num_cols);
   for (i = 0; i < cfile.cinfo.num_cols; i++) {
     cfile.cinfo.col_fmt[i] = get_column_format(i);
     cfile.cinfo.col_title[i] = g_strdup(get_column_title(i));
@@ -1801,6 +2034,7 @@ main(int argc, char *argv[])
       cfile.cinfo.col_buf[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_INFO_LEN);
     else
       cfile.cinfo.col_buf[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_LEN);
+    cfile.cinfo.col_fence[i] = 0;
     cfile.cinfo.col_expr[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_LEN);
     cfile.cinfo.col_expr_val[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_LEN);
   }
@@ -1812,52 +2046,91 @@ main(int argc, char *argv[])
     else if (capture_opts.snaplen < MIN_PACKET_SIZE)
       capture_opts.snaplen = MIN_PACKET_SIZE;
   }
-  
+
   /* Check the value range of the ringbuffer_num_files parameter */
   if (capture_opts.ringbuffer_num_files < RINGBUFFER_MIN_NUM_FILES)
     capture_opts.ringbuffer_num_files = RINGBUFFER_MIN_NUM_FILES;
   else if (capture_opts.ringbuffer_num_files > RINGBUFFER_MAX_NUM_FILES)
     capture_opts.ringbuffer_num_files = RINGBUFFER_MAX_NUM_FILES;
 #endif
-  
+
   rc_file = get_persconffile_path(RC_FILE, FALSE);
   gtk_rc_parse(rc_file);
 
   /* Try to load the regular and boldface fixed-width fonts */
+#if GTK_MAJOR_VERSION < 2
   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);
+#else
+  m_r_font = pango_font_description_from_string(prefs->gui_font_name);
+  m_b_font = pango_font_description_copy(m_r_font);
+  pango_font_description_set_weight(m_b_font, PANGO_WEIGHT_BOLD);
+#endif
   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
+#if GTK_MAJOR_VERSION < 2
        fprintf(stderr, "ethereal: Warning: font %s not found - defaulting to 6x13 and 6x13bold\n",
+#else
+       fprintf(stderr, "ethereal: Warning: font %s not found - defaulting to Monospace 9\n",
+#endif
                prefs->gui_font_name);
     } else {
+#if GTK_MAJOR_VERSION < 2
       gdk_font_unref(m_r_font);
+#else
+      pango_font_description_free(m_r_font);
+#endif
     }
     if (m_b_font == NULL) {
 #ifdef HAVE_LIBPCAP
       if (!capture_child)
 #endif
+#if GTK_MAJOR_VERSION < 2
        fprintf(stderr, "ethereal: Warning: font %s not found - defaulting to 6x13 and 6x13bold\n",
                bold_font_name);
+#else
+        fprintf(stderr, "ethereal: Warning: bold font %s not found - defaulting"
+                        " to Monospace 9\n", prefs->gui_font_name);
+#endif
     } else {
+#if GTK_MAJOR_VERSION < 2
       gdk_font_unref(m_b_font);
+#else
+      pango_font_description_free(m_b_font);
+#endif
     }
+#if GTK_MAJOR_VERSION < 2
     g_free(bold_font_name);
     if ((m_r_font = gdk_font_load("6x13")) == NULL) {
       fprintf(stderr, "ethereal: Error: font 6x13 not found\n");
+#else
+    if ((m_r_font = pango_font_description_from_string("Monospace 9")) == NULL)
+    {
+            fprintf(stderr, "ethereal: Error: font Monospace 9 not found\n");
+#endif
       exit(1);
     }
+#if GTK_MAJOR_VERSION < 2
     if ((m_b_font = gdk_font_load("6x13bold")) == NULL) {
       fprintf(stderr, "ethereal: Error: font 6x13bold not found\n");
+#else
+    if ((m_b_font = pango_font_description_copy(m_r_font)) == NULL) {
+            fprintf(stderr, "ethereal: Error: font Monospace 9 bold not found\n");
+#endif
       exit(1);
     }
     g_free(prefs->gui_font_name);
+#if GTK_MAJOR_VERSION < 2
     prefs->gui_font_name = g_strdup("6x13");
+#else
+    pango_font_description_set_weight(m_b_font, PANGO_WEIGHT_BOLD);
+    prefs->gui_font_name = g_strdup("Monospace 9");
+#endif
   }
 
   /* Call this for the side-effects that set_fonts() produces */
@@ -1870,12 +2143,21 @@ main(int argc, char *argv[])
      to a file that our parent will read? */
   if (!capture_child) {
 #endif
-    /* No.  Pop up the main window, and read in a capture file if
+    /* No.  Pop up the main window, register menus for taps (which we
+       must do after creating the main window, so that we can add
+       menu items to the main menu), and read in a capture file if
        we were told to. */
-
     create_main_window(pl_size, tv_size, bv_size, prefs);
+    register_all_tap_menus();
     set_menus_for_capture_file(FALSE);
 
+    /* open tap windows after creating the main window to avoid GTK warnings */
+    if (tap_opt && tli) {
+      (*tli->func)(tap_opt);
+      g_free(tap_opt);
+    }
+
+    colors_init();
     colfilter_init();
 
     /* If we were given the name of a capture file, read it in now;
@@ -1917,6 +2199,8 @@ main(int argc, char *argv[])
              argument. */
           s = get_dirname(cf_name);
          set_last_open_dir(s);
+          g_free(cf_name);
+          cf_name = NULL;
         } else {
           if (rfcode != NULL)
             dfilter_free(rfcode);
@@ -1944,6 +2228,8 @@ main(int argc, char *argv[])
       simple_dialog(ESD_TYPE_WARN, NULL,
         "Could not open your preferences file\n\"%s\": %s.", pf_path,
         strerror(pf_open_errno));
+      g_free(pf_path);
+      pf_path = NULL;
   }
 
   /* If the user's capture filter file exists but we failed to open it,
@@ -1982,6 +2268,13 @@ main(int argc, char *argv[])
     if (start_capture) {
       /* "-k" was specified; start a capture. */
       do_capture(save_file);
+      if (save_file != NULL) {
+        /* Save the directory name for future file dialogs. */
+        s = get_dirname(save_file);  /* Overwrites save_file */
+        set_last_open_dir(s);
+        g_free(save_file);
+        save_file = NULL;
+      }
     }
     else {
       set_menus_for_capture_in_progress(FALSE);
@@ -1998,10 +2291,10 @@ main(int argc, char *argv[])
                 documentation correctly, gdk_window_get_deskrelative_origin applies
                 mainly to Enlightenment and gdk_window_get_root_origin applies for
                 all other WMs.
-          
+
           The code below tries both routines, and picks the one that returns
           the upper-left-most coordinates.
-          
+
           More info at:
 
           http://mail.gnome.org/archives/gtk-devel-list/2001-March/msg00289.html
@@ -2032,7 +2325,7 @@ main(int argc, char *argv[])
                                prefs_write_needed = TRUE;
                        }
                }
-               
+
                if (prefs->gui_geometry_save_size) {
                        if (top_level->window != NULL) {
                                /* XXX - Is this the "approved" method? */
@@ -2047,12 +2340,15 @@ main(int argc, char *argv[])
                                prefs_write_needed = TRUE;
                        }
                }
-               
+
                if (prefs_write_needed) {
                        write_prefs(&pf_path);
                }
+       } else {
+               /* Ignore errors silently */
+               g_free(pf_path);
        }
-       
+
   epan_cleanup();
   g_free(rc_file);
 
@@ -2159,6 +2455,7 @@ console_log_handler(const char *log_domain, GLogLevelFlags log_level,
 }
 #endif
 
+#if GTK_MAJOR_VERSION < 2
 /* Given a font name, construct the name of the next heavier version of
    that font. */
 
@@ -2184,7 +2481,7 @@ static const struct {
        { "bold",       "ultrabold" }
 };
 #define        N_WEIGHTS       (sizeof weight_map / sizeof weight_map[0])
-       
+
 char *
 boldify(const char *font_name)
 {
@@ -2231,234 +2528,258 @@ not_xlfd:
        bold_font_name = g_strconcat(font_name, "bold", NULL);
        return bold_font_name;
 }
-
+#endif
 
 static void
 create_main_window (gint pl_size, gint tv_size, gint bv_size, e_prefs *prefs)
 {
-  GtkWidget           *main_vbox, *menubar, *u_pane, *l_pane,
-                      *stat_hbox, *column_lb,
-                      *filter_bt, *filter_cm, *filter_te,
-                      *filter_apply,
-                      *filter_reset;
-  GList               *filter_list = NULL;
-  GtkAccelGroup       *accel;
-  GtkStyle            *win_style;
-  GdkBitmap           *ascend_bm, *descend_bm;
-  GdkPixmap           *ascend_pm, *descend_pm;
-  column_arrows       *col_arrows;
-  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);
-  gtk_widget_set_name(top_level, "main window");
-  gtk_signal_connect(GTK_OBJECT(top_level), "delete_event", 
-    GTK_SIGNAL_FUNC(main_window_delete_event_cb), NULL);
-  gtk_signal_connect (GTK_OBJECT (top_level), "realize",
-    GTK_SIGNAL_FUNC (window_icon_realize_cb), NULL);
-  gtk_window_set_title(GTK_WINDOW(top_level), "The Ethereal Network Analyzer");
-  if (prefs->gui_geometry_save_position) {
-    gtk_widget_set_uposition(GTK_WIDGET(top_level),
-      prefs->gui_geometry_main_x, prefs->gui_geometry_main_y);
-  }
-  if (prefs->gui_geometry_save_size) {
-    gtk_widget_set_usize(GTK_WIDGET(top_level),
-      prefs->gui_geometry_main_width, prefs->gui_geometry_main_height);
-  } else {
-    gtk_widget_set_usize(GTK_WIDGET(top_level), DEF_WIDTH, -1);
-  }
-  gtk_window_set_policy(GTK_WINDOW(top_level), TRUE, TRUE, FALSE);
-
-  /* Container for menu bar, paned windows and progress/info box */
-  main_vbox = gtk_vbox_new(FALSE, 1);
-  gtk_container_border_width(GTK_CONTAINER(main_vbox), 1);
-  gtk_container_add(GTK_CONTAINER(top_level), main_vbox);
-  gtk_widget_show(main_vbox);
-
-  /* Menu bar */
-  get_main_menu(&menubar, &accel);
-  gtk_window_add_accel_group(GTK_WINDOW(top_level), accel);
-  gtk_box_pack_start(GTK_BOX(main_vbox), menubar, FALSE, TRUE, 0);
-  gtk_widget_show(menubar);
-
-  /* Panes for the packet list, tree, and byte view */
-  u_pane = gtk_vpaned_new();
-  gtk_paned_gutter_size(GTK_PANED(u_pane), (GTK_PANED(u_pane))->handle_size);
-  l_pane = gtk_vpaned_new();
-  gtk_paned_gutter_size(GTK_PANED(l_pane), (GTK_PANED(l_pane))->handle_size);
-  gtk_container_add(GTK_CONTAINER(main_vbox), u_pane);
-  gtk_widget_show(l_pane);
-  gtk_paned_add2(GTK_PANED(u_pane), l_pane);
-  gtk_widget_show(u_pane);
-
-  /* Packet list */
-  pkt_scrollw = scrolled_window_new(NULL, NULL);
-  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW(pkt_scrollw),
-    GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
-  gtk_widget_show(pkt_scrollw);
-  gtk_paned_add1(GTK_PANED(u_pane), pkt_scrollw);
-
-  packet_list = gtk_clist_new(cfile.cinfo.num_cols);
-  /* Column titles are filled in below */
-  gtk_container_add(GTK_CONTAINER(pkt_scrollw), packet_list);
-
-  col_arrows = (column_arrows *) g_malloc(sizeof(column_arrows) * cfile.cinfo.num_cols);
-  
-  set_plist_sel_browse(prefs->gui_plist_sel_browse);
-  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), col_arrows);
-  gtk_signal_connect(GTK_OBJECT(packet_list), "select_row",
-    GTK_SIGNAL_FUNC(packet_list_select_cb), NULL);
-  gtk_signal_connect(GTK_OBJECT(packet_list), "unselect_row",
-    GTK_SIGNAL_FUNC(packet_list_unselect_cb), NULL);
-  for (i = 0; i < cfile.cinfo.num_cols; i++) {
-    if (get_column_resize_type(cfile.cinfo.col_fmt[i]) != RESIZE_MANUAL)
-      gtk_clist_set_column_auto_resize(GTK_CLIST(packet_list), i, TRUE);
-
-    /* Right-justify the packet number column. */
-    if (cfile.cinfo.col_fmt[i] == COL_NUMBER)
-      gtk_clist_set_column_justification(GTK_CLIST(packet_list), i, 
-        GTK_JUSTIFY_RIGHT);
-  }
-  gtk_widget_set_usize(packet_list, -1, pl_size);
-  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);
-  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(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);
-
-  /* Byte view. */
-  byte_nb_ptr = create_byte_view(bv_size, l_pane);
-
-  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);
-
-  filter_bt = gtk_button_new_with_label("Filter:");
-  gtk_signal_connect(GTK_OBJECT(filter_bt), "clicked",
-    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);
-  
-  filter_cm = gtk_combo_new();
-  filter_list = g_list_append (filter_list, "");
-  gtk_combo_set_popdown_strings(GTK_COMBO(filter_cm), filter_list);
-  gtk_combo_disable_activate(GTK_COMBO(filter_cm));
-  gtk_combo_set_case_sensitive(GTK_COMBO(filter_cm), TRUE);
-  gtk_object_set_data(GTK_OBJECT(filter_cm), E_DFILTER_FL_KEY, filter_list);
-  filter_te = GTK_COMBO(filter_cm)->entry;
-  gtk_object_set_data(GTK_OBJECT(filter_bt), E_FILT_TE_PTR_KEY, filter_te);
-  gtk_object_set_data(GTK_OBJECT(filter_te), E_DFILTER_CM_KEY, filter_cm);
-  gtk_box_pack_start(GTK_BOX(stat_hbox), filter_cm, TRUE, TRUE, 3);
-  gtk_signal_connect(GTK_OBJECT(filter_te), "activate",
-    GTK_SIGNAL_FUNC(filter_activate_cb), filter_te);
-  gtk_widget_show(filter_cm);
-
-  filter_reset = gtk_button_new_with_label("Reset");
-  gtk_object_set_data(GTK_OBJECT(filter_reset), E_DFILTER_TE_KEY, filter_te);
-  gtk_signal_connect(GTK_OBJECT(filter_reset), "clicked",
-                    GTK_SIGNAL_FUNC(filter_reset_cb), NULL);
-  gtk_box_pack_start(GTK_BOX(stat_hbox), filter_reset, FALSE, TRUE, 1);
-  gtk_widget_show(filter_reset);
-
-  filter_apply = gtk_button_new_with_label("Apply");
-  gtk_object_set_data(GTK_OBJECT(filter_apply), E_DFILTER_CM_KEY, filter_cm);
-  gtk_signal_connect(GTK_OBJECT(filter_apply), "clicked",
-                     GTK_SIGNAL_FUNC(filter_activate_cb), filter_te);
-  gtk_box_pack_start(GTK_BOX(stat_hbox), filter_apply, FALSE, TRUE, 1);
-  gtk_widget_show(filter_apply);
-
-  /* Sets the text entry widget pointer as the E_DILTER_TE_KEY data
-   * of any widget that ends up calling a callback which needs
-   * that text entry pointer */
-  set_menu_object_data("/File/Open...", E_DFILTER_TE_KEY, filter_te);
-  set_menu_object_data("/File/Reload", E_DFILTER_TE_KEY, filter_te);
-  set_menu_object_data("/Edit/Filters...", E_FILT_TE_PTR_KEY, filter_te);
-  set_menu_object_data("/Tools/Follow TCP Stream", E_DFILTER_TE_KEY, filter_te);
-  set_menu_object_data("/Display/Match/Selected", E_DFILTER_TE_KEY, filter_te);
-  set_menu_object_data("/Display/Match/Not Selected", E_DFILTER_TE_KEY, filter_te);
-  set_menu_object_data("/Display/Match/And Selected", E_DFILTER_TE_KEY, filter_te);
-  set_menu_object_data("/Display/Match/Or Selected", E_DFILTER_TE_KEY, filter_te);
-  set_menu_object_data("/Display/Match/And Not Selected", E_DFILTER_TE_KEY, filter_te);
-  set_menu_object_data("/Display/Match/Or Not Selected", E_DFILTER_TE_KEY, filter_te);
-  set_menu_object_data("/Display/Prepare/Selected", E_DFILTER_TE_KEY, filter_te);
-  set_menu_object_data("/Display/Prepare/Not Selected", E_DFILTER_TE_KEY, filter_te);
-  set_menu_object_data("/Display/Prepare/And Selected", E_DFILTER_TE_KEY, filter_te);
-  set_menu_object_data("/Display/Prepare/Or Selected", E_DFILTER_TE_KEY, filter_te);
-  set_menu_object_data("/Display/Prepare/And Not Selected", E_DFILTER_TE_KEY, filter_te);
-  set_menu_object_data("/Display/Prepare/Or Not Selected", E_DFILTER_TE_KEY, filter_te);
-  gtk_object_set_data(GTK_OBJECT(popup_menu_object), E_DFILTER_TE_KEY, filter_te);
-  gtk_object_set_data(GTK_OBJECT(popup_menu_object), E_MPACKET_LIST_KEY, packet_list);
-
-  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);
-
-  /* Fill in column titles.  This must be done after the top level window
-     is displayed. */
-  win_style = gtk_widget_get_style(top_level);
-  ascend_pm = gdk_pixmap_create_from_xpm_d(top_level->window, &ascend_bm,
-       &win_style->bg[GTK_STATE_NORMAL], (gchar **)clist_ascend_xpm);
-  descend_pm = gdk_pixmap_create_from_xpm_d(top_level->window, &descend_bm,
-       &win_style->bg[GTK_STATE_NORMAL], (gchar **)clist_descend_xpm);
-  for (i = 0; i < cfile.cinfo.num_cols; i++) {
-    col_arrows[i].table = gtk_table_new(2, 2, FALSE);
-    gtk_table_set_col_spacings(GTK_TABLE(col_arrows[i].table), 5);
-    column_lb = gtk_label_new(cfile.cinfo.col_title[i]);
-    gtk_table_attach(GTK_TABLE(col_arrows[i].table), column_lb, 0, 1, 0, 2,
-       GTK_SHRINK, GTK_SHRINK, 0, 0);
-    gtk_widget_show(column_lb);
-    col_arrows[i].ascend_pm = gtk_pixmap_new(ascend_pm, ascend_bm);
-    gtk_table_attach(GTK_TABLE(col_arrows[i].table), col_arrows[i].ascend_pm, 
-       1, 2, 1, 2, GTK_SHRINK, GTK_SHRINK, 0, 0);
-    if (i == 0) {
-      gtk_widget_show(col_arrows[i].ascend_pm);
+    GtkWidget     *main_vbox, *menubar, *u_pane, *l_pane,
+                  *stat_hbox, *column_lb,
+                  *filter_bt, *filter_cm, *filter_te,
+                  *filter_apply,
+                  *filter_reset;
+    GList         *filter_list = NULL;
+    GtkAccelGroup *accel;
+    GtkStyle      *win_style;
+    GdkBitmap     *ascend_bm, *descend_bm;
+    GdkPixmap     *ascend_pm, *descend_pm;
+    column_arrows *col_arrows;
+    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);
+    gtk_widget_set_name(top_level, "main window");
+    SIGNAL_CONNECT(top_level, "delete_event", main_window_delete_event_cb,
+                   NULL);
+    SIGNAL_CONNECT(top_level, "realize", window_icon_realize_cb, NULL);
+    gtk_window_set_title(GTK_WINDOW(top_level), "The Ethereal Network Analyzer");
+    if (prefs->gui_geometry_save_position) {
+        gtk_widget_set_uposition(GTK_WIDGET(top_level),
+                                 prefs->gui_geometry_main_x,
+                                 prefs->gui_geometry_main_y);
     }
-    col_arrows[i].descend_pm = gtk_pixmap_new(descend_pm, descend_bm);
-    gtk_table_attach(GTK_TABLE(col_arrows[i].table), col_arrows[i].descend_pm,
-       1, 2, 0, 1, GTK_SHRINK, GTK_SHRINK, 0, 0);
-    gtk_clist_set_column_widget(GTK_CLIST(packet_list), i, col_arrows[i].table);
-    gtk_widget_show(col_arrows[i].table);
-  }
-  gtk_clist_column_titles_show(GTK_CLIST(packet_list));
+    if (prefs->gui_geometry_save_size) {
+        WIDGET_SET_SIZE(top_level, prefs->gui_geometry_main_width,
+                        prefs->gui_geometry_main_height);
+    } else {
+        WIDGET_SET_SIZE(top_level, DEF_WIDTH, -1);
+    }
+    gtk_window_set_policy(GTK_WINDOW(top_level), TRUE, TRUE, FALSE);
+
+    /* Container for menu bar, paned windows and progress/info box */
+    main_vbox = gtk_vbox_new(FALSE, 1);
+    gtk_container_border_width(GTK_CONTAINER(main_vbox), 1);
+    gtk_container_add(GTK_CONTAINER(top_level), main_vbox);
+    gtk_widget_show(main_vbox);
+
+    /* Menu bar */
+    get_main_menu(&menubar, &accel);
+    gtk_window_add_accel_group(GTK_WINDOW(top_level), accel);
+    gtk_box_pack_start(GTK_BOX(main_vbox), menubar, FALSE, TRUE, 0);
+    gtk_widget_show(menubar);
+
+    /* Panes for the packet list, tree, and byte view */
+    u_pane = gtk_vpaned_new();
+    gtk_paned_gutter_size(GTK_PANED(u_pane), (GTK_PANED(u_pane))->handle_size);
+    l_pane = gtk_vpaned_new();
+    gtk_paned_gutter_size(GTK_PANED(l_pane), (GTK_PANED(l_pane))->handle_size);
+    gtk_container_add(GTK_CONTAINER(main_vbox), u_pane);
+    gtk_widget_show(l_pane);
+    gtk_paned_add2(GTK_PANED(u_pane), l_pane);
+    gtk_widget_show(u_pane);
+
+    /* Packet list */
+    pkt_scrollw = scrolled_window_new(NULL, NULL);
+    gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW(pkt_scrollw),
+                                    GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+    gtk_widget_show(pkt_scrollw);
+    gtk_paned_add1(GTK_PANED(u_pane), pkt_scrollw);
+
+    packet_list = gtk_clist_new(cfile.cinfo.num_cols);
+    /* Column titles are filled in below */
+    gtk_container_add(GTK_CONTAINER(pkt_scrollw), packet_list);
+
+    col_arrows = (column_arrows *) g_malloc(sizeof(column_arrows) *
+                                            cfile.cinfo.num_cols);
+
+    set_plist_sel_browse(prefs->gui_plist_sel_browse);
+    set_plist_font(m_r_font);
+    gtk_widget_set_name(packet_list, "packet list");
+    SIGNAL_CONNECT(packet_list, "click-column", packet_list_click_column_cb,
+                   col_arrows);
+    SIGNAL_CONNECT(packet_list, "select-row", packet_list_select_cb, NULL);
+    SIGNAL_CONNECT(packet_list, "unselect-row", packet_list_unselect_cb, NULL);
+    for (i = 0; i < cfile.cinfo.num_cols; i++) {
+        if (get_column_resize_type(cfile.cinfo.col_fmt[i]) != RESIZE_MANUAL)
+            gtk_clist_set_column_auto_resize(GTK_CLIST(packet_list), i, TRUE);
+
+        /* Right-justify the packet number column. */
+        if (cfile.cinfo.col_fmt[i] == COL_NUMBER)
+            gtk_clist_set_column_justification(GTK_CLIST(packet_list), i,
+                                               GTK_JUSTIFY_RIGHT);
+    }
+    WIDGET_SET_SIZE(packet_list, -1, pl_size);
+    SIGNAL_CONNECT(packet_list, "button_press_event", popup_menu_handler,
+                   OBJECT_GET_DATA(popup_menu_object, PM_PACKET_LIST_KEY));
+    SIGNAL_CONNECT(packet_list, "button_press_event",
+                   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 */
+#if GTK_MAJOR_VERSION < 2
+    item_style = gtk_style_new();
+    gdk_font_unref(item_style->font);
+    item_style->font = m_r_font;
+#endif
+    create_tree_view(tv_size, prefs, l_pane, &tv_scrollw, &tree_view);
+#if GTK_MAJOR_VERSION < 2
+    SIGNAL_CONNECT(tree_view, "tree-select-row", tree_view_select_row_cb, NULL);
+    SIGNAL_CONNECT(tree_view, "tree-unselect-row", tree_view_unselect_row_cb,
+                   NULL);
+#else
+    SIGNAL_CONNECT(gtk_tree_view_get_selection(GTK_TREE_VIEW(tree_view)),
+                   "changed", tree_view_selection_changed_cb, NULL);
+#endif
+    SIGNAL_CONNECT(tree_view, "button_press_event", popup_menu_handler,
+                   OBJECT_GET_DATA(popup_menu_object, PM_TREE_VIEW_KEY));
+    gtk_widget_show(tree_view);
+
+    /* Byte view. */
+    byte_nb_ptr = create_byte_view(bv_size, l_pane);
+
+    SIGNAL_CONNECT(byte_nb_ptr, "button_press_event", popup_menu_handler,
+                   OBJECT_GET_DATA(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);
+
+    filter_bt = gtk_button_new_with_label("Filter:");
+    SIGNAL_CONNECT(filter_bt, "clicked", display_filter_construct_cb, &args);
+    gtk_box_pack_start(GTK_BOX(stat_hbox), filter_bt, FALSE, TRUE, 0);
+    gtk_widget_show(filter_bt);
+
+    filter_cm = gtk_combo_new();
+    filter_list = g_list_append (filter_list, "");
+    gtk_combo_set_popdown_strings(GTK_COMBO(filter_cm), filter_list);
+    gtk_combo_disable_activate(GTK_COMBO(filter_cm));
+    gtk_combo_set_case_sensitive(GTK_COMBO(filter_cm), TRUE);
+    OBJECT_SET_DATA(filter_cm, E_DFILTER_FL_KEY, filter_list);
+    filter_te = GTK_COMBO(filter_cm)->entry;
+    OBJECT_SET_DATA(filter_bt, E_FILT_TE_PTR_KEY, filter_te);
+    OBJECT_SET_DATA(filter_te, E_DFILTER_CM_KEY, filter_cm);
+    gtk_box_pack_start(GTK_BOX(stat_hbox), filter_cm, TRUE, TRUE, 3);
+    SIGNAL_CONNECT(filter_te, "activate", filter_activate_cb, filter_te);
+    gtk_widget_show(filter_cm);
+
+#if GTK_MAJOR_VERSION < 2
+    filter_reset = gtk_button_new_with_label("Reset");
+#else
+    filter_reset = gtk_button_new_from_stock(GTK_STOCK_CLEAR);
+#endif    
+    OBJECT_SET_DATA(filter_reset, E_DFILTER_TE_KEY, filter_te);
+    SIGNAL_CONNECT(filter_reset, "clicked", filter_reset_cb, NULL);
+    gtk_box_pack_start(GTK_BOX(stat_hbox), filter_reset, FALSE, TRUE, 1);
+    gtk_widget_show(filter_reset);
+
+#if GTK_MAJOR_VERSION < 2
+    filter_apply = gtk_button_new_with_label("Apply");
+#else
+    filter_apply = gtk_button_new_from_stock(GTK_STOCK_APPLY);
+#endif
+    OBJECT_SET_DATA(filter_apply, E_DFILTER_CM_KEY, filter_cm);
+    SIGNAL_CONNECT(filter_apply, "clicked", filter_activate_cb, filter_te);
+    gtk_box_pack_start(GTK_BOX(stat_hbox), filter_apply, FALSE, TRUE, 1);
+    gtk_widget_show(filter_apply);
+
+    /* Sets the text entry widget pointer as the E_DILTER_TE_KEY data
+     * of any widget that ends up calling a callback which needs
+     * that text entry pointer */
+    set_menu_object_data("/File/Open...", E_DFILTER_TE_KEY, filter_te);
+    set_menu_object_data("/File/Reload", E_DFILTER_TE_KEY, filter_te);
+    set_menu_object_data("/Edit/Filters...", E_FILT_TE_PTR_KEY, filter_te);
+    set_menu_object_data("/Tools/Follow TCP Stream", E_DFILTER_TE_KEY,
+                         filter_te);
+    set_menu_object_data("/Display/Match/Selected", E_DFILTER_TE_KEY,
+                         filter_te);
+    set_menu_object_data("/Display/Match/Not Selected", E_DFILTER_TE_KEY,
+                         filter_te);
+    set_menu_object_data("/Display/Match/And Selected", E_DFILTER_TE_KEY,
+                         filter_te);
+    set_menu_object_data("/Display/Match/Or Selected", E_DFILTER_TE_KEY,
+                         filter_te);
+    set_menu_object_data("/Display/Match/And Not Selected", E_DFILTER_TE_KEY,
+                         filter_te);
+    set_menu_object_data("/Display/Match/Or Not Selected", E_DFILTER_TE_KEY,
+                         filter_te);
+    set_menu_object_data("/Display/Prepare/Selected", E_DFILTER_TE_KEY,
+                         filter_te);
+    set_menu_object_data("/Display/Prepare/Not Selected", E_DFILTER_TE_KEY,
+                         filter_te);
+    set_menu_object_data("/Display/Prepare/And Selected", E_DFILTER_TE_KEY,
+                         filter_te);
+    set_menu_object_data("/Display/Prepare/Or Selected", E_DFILTER_TE_KEY,
+                         filter_te);
+    set_menu_object_data("/Display/Prepare/And Not Selected", E_DFILTER_TE_KEY,
+                         filter_te);
+    set_menu_object_data("/Display/Prepare/Or Not Selected", E_DFILTER_TE_KEY,
+                         filter_te);
+    OBJECT_SET_DATA(popup_menu_object, E_DFILTER_TE_KEY, filter_te);
+    OBJECT_SET_DATA(popup_menu_object, E_MPACKET_LIST_KEY, packet_list);
+
+    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);
+
+    /* Fill in column titles.  This must be done after the top level window
+       is displayed. */
+    win_style = gtk_widget_get_style(top_level);
+    ascend_pm = gdk_pixmap_create_from_xpm_d(top_level->window, &ascend_bm,
+                                             &win_style->bg[GTK_STATE_NORMAL],
+                                             (gchar **)clist_ascend_xpm);
+    descend_pm = gdk_pixmap_create_from_xpm_d(top_level->window, &descend_bm,
+                                              &win_style->bg[GTK_STATE_NORMAL],
+                                              (gchar **)clist_descend_xpm);
+    for (i = 0; i < cfile.cinfo.num_cols; i++) {
+        col_arrows[i].table = gtk_table_new(2, 2, FALSE);
+        gtk_table_set_col_spacings(GTK_TABLE(col_arrows[i].table), 5);
+        column_lb = gtk_label_new(cfile.cinfo.col_title[i]);
+        gtk_table_attach(GTK_TABLE(col_arrows[i].table), column_lb, 0, 1, 0, 2,
+                         GTK_SHRINK, GTK_SHRINK, 0, 0);
+        gtk_widget_show(column_lb);
+        col_arrows[i].ascend_pm = gtk_pixmap_new(ascend_pm, ascend_bm);
+        gtk_table_attach(GTK_TABLE(col_arrows[i].table),
+                         col_arrows[i].ascend_pm,
+                         1, 2, 1, 2, GTK_SHRINK, GTK_SHRINK, 0, 0);
+        if (i == 0) {
+            gtk_widget_show(col_arrows[i].ascend_pm);
+        }
+        col_arrows[i].descend_pm = gtk_pixmap_new(descend_pm, descend_bm);
+        gtk_table_attach(GTK_TABLE(col_arrows[i].table),
+                         col_arrows[i].descend_pm,
+                         1, 2, 0, 1, GTK_SHRINK, GTK_SHRINK, 0, 0);
+        gtk_clist_set_column_widget(GTK_CLIST(packet_list), i,
+                                    col_arrows[i].table);
+        gtk_widget_show(col_arrows[i].table);
+    }
+    gtk_clist_column_titles_show(GTK_CLIST(packet_list));
 }
 
 
@@ -2473,7 +2794,10 @@ set_last_open_dir(char *dirname)
 
        if (dirname) {
                len = strlen(dirname);
-               if (dirname[len-1] != G_DIR_SEPARATOR) {
+               if (dirname[len-1] == G_DIR_SEPARATOR) {
+                       last_open_dir = g_strconcat(dirname, NULL);
+               }
+               else {
                        last_open_dir = g_strconcat(dirname, G_DIR_SEPARATOR_S,
                                NULL);
                }