From Alejandro Vaquero
[obnox/wireshark/wip.git] / gtk / main.c
index 5074e7dd71d83f1da2d67dc03a2f5e6d8559a455..6c95789e567757fd4021bf1b0f7334b91c1cdacb 100644 (file)
@@ -1,6 +1,6 @@
 /* main.c
  *
- * $Id: main.c,v 1.419 2004/03/20 06:34:08 guy Exp $
+ * $Id$
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@ethereal.com>
@@ -64,7 +64,7 @@
 #include "getopt.h"
 #endif
 
-#ifdef WIN32 /* Needed for console I/O */
+#ifdef _WIN32 /* Needed for console I/O */
 #include <fcntl.h>
 #include <conio.h>
 #endif
 #include <epan/epan.h>
 #include <epan/filesystem.h>
 #include <epan/epan_dissect.h>
-
-#include "cvsversion.h"
-#include "main.h"
 #include <epan/timestamp.h>
 #include <epan/packet.h>
-#include "capture.h"
-#include "summary.h"
+#include <epan/plugins.h>
+#include <epan/dfilter/dfilter.h>
+#include <epan/strutil.h>
+#include <epan/addr_resolv.h>
+
+/* general (not GTK specific) */
+#include "svnversion.h"
 #include "file.h"
+#include "summary.h"
 #include "filters.h"
 #include "disabled_protos.h"
-#include "prefs.h"
-#include "menu.h"
-#include "../menu.h"
+#include <epan/prefs.h>
+#include "filter_dlg.h"
+#include "layout_prefs.h"
 #include "color.h"
 #include "color_filters.h"
-#include "color_utils.h"
-#include "filter_prefs.h"
-#include "file_dlg.h"
-#include "column.h"
 #include "print.h"
-#include <epan/resolv.h>
+#include "simple_dialog.h"
+#include "register.h"
+#include <epan/prefs-int.h>
+#include "ringbuffer.h"
+#include "../ui_util.h"     /* beware: ui_util.h exists twice! */
+#include <epan/tap.h>
+#include "util.h"
+#include "clopts_common.h"
+#include "version_info.h"
+#include "capture.h"
+#include "merge.h"
 #ifdef HAVE_LIBPCAP
 #include "pcap-util.h"
 #endif
+#ifdef _WIN32
+#include "capture-wpcap.h"
+#endif
+#if GTK_MAJOR_VERSION < 2 && GTK_MINOR_VERSION < 3
+#include "ethclist.h"
+#endif
+
+/* GTK related */
 #include "statusbar.h"
 #include "alert_box.h"
-#include "simple_dialog.h"
 #include "dlg_utils.h"
+#include "gtkglobals.h"
+#include "colors.h"
+#include "ui_util.h"        /* beware: ui_util.h exists twice! */
+#include "compat_macros.h"
+
+#include "main.h"
+#include "menu.h"
+#include "../main_window.h"
+#include "../menu.h"
+#include "file_dlg.h"
+#include <epan/column.h>
 #include "proto_draw.h"
-#include <epan/dfilter/dfilter.h>
 #include "keys.h"
 #include "packet_win.h"
-#include "gtkglobals.h"
-#include <epan/plugins.h>
-#include "colors.h"
-#include <epan/strutil.h>
-#include "register.h"
-#include <prefs-int.h>
-#include "ringbuffer.h"
-#include "../ui_util.h"
-#include "ui_util.h"
 #include "toolbar.h"
-#include "../tap.h"
-#include "../util.h"
-#include "../version_info.h"
-#include "compat_macros.h"
 #include "find_dlg.h"
 #include "packet_list.h"
 #include "recent.h"
 #include "follow_dlg.h"
-#include <epan/timestamp.h>
+#include "font_utils.h"
+#include "about_dlg.h"
+#include "help_dlg.h"
+#include "decode_as_dlg.h"
+#include "webbrowser.h"
+#include "capture_dlg.h"
+#include "../image/eicon3d64.xpm"
+#include "capture_ui_utils.h"
 
-#ifdef WIN32
-#include "capture-wpcap.h"
+
+
+/*
+ * File under personal preferences directory in which GTK settings for
+ * Ethereal are stored.
+ */
+#define RC_FILE "gtkrc"
+
+#ifdef HAVE_LIBPCAP
+#define DEF_READY_MESSAGE " Ready to load or capture"
+#else
+#define DEF_READY_MESSAGE " Ready to load file"
 #endif
 
 capture_file cfile;
 GtkWidget   *main_display_filter_widget=NULL;
 GtkWidget   *top_level = NULL, *tree_view, *byte_nb_ptr, *tv_scrollw;
-GtkWidget   *upper_pane, *lower_pane;
-GtkWidget   *menubar, *main_vbox, *main_tb, *pkt_scrollw, *stat_hbox, *filter_tb;
+static GtkWidget   *main_pane_v1, *main_pane_v2, *main_pane_h1, *main_pane_h2;
+static GtkWidget   *main_first_pane, *main_second_pane;
+static GtkWidget   *status_pane;
+static GtkWidget   *menubar, *main_vbox, *main_tb, *pkt_scrollw, *stat_hbox, *filter_tb;
 static GtkWidget       *info_bar;
 static GtkWidget    *packets_bar = NULL;
-#if GTK_MAJOR_VERSION < 2
-GdkFont     *m_r_font, *m_b_font;
-guint       m_font_height, m_font_width;
-#else
-PangoFontDescription *m_r_font, *m_b_font;
-#endif
+static GtkWidget    *welcome_pane;
 static guint    main_ctx, file_ctx, help_ctx;
 static guint        packets_ctx;
 static gchar        *packets_str = NULL;
-static GString *comp_info_str, *runtime_info_str;
+GString *comp_info_str, *runtime_info_str;
 gchar       *ethereal_path = NULL;
-gchar       *last_open_dir = NULL;
-static gboolean updated_last_open_dir = FALSE;
-
-#if GTK_MAJOR_VERSION < 2
-GtkStyle *item_style;
-#endif
+gboolean have_capture_file = FALSE; /* XXX - is there an aquivalent in cfile? */
 
-#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);
+#ifdef _WIN32
+static gboolean has_console;   /* TRUE if app has console */
+/*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);
@@ -164,247 +185,19 @@ static void console_log_handler(const char *log_domain,
 
 #ifdef HAVE_LIBPCAP
 static gboolean list_link_layer_types;
+capture_options global_capture_opts;
+capture_options *capture_opts = &global_capture_opts;
 #endif
 
-static void about_ethereal_destroy_cb(GtkWidget *, gpointer);
+
 static void create_main_window(gint, gint, gint, e_prefs*);
-static void file_quit_answered_cb(gpointer dialog _U_, gint btn, gpointer data _U_);
+static void show_main_window(gboolean);
+static void file_quit_answered_cb(gpointer dialog, gint btn, gpointer data);
 static void main_save_window_geometry(GtkWidget *widget);
-#ifdef WIN32
-#if GTK_MAJOR_VERSION >= 2
-static void try_to_get_windows_font_gtk2 (void);
-#endif
-#endif
 
 #define E_DFILTER_CM_KEY          "display_filter_combo"
 #define E_DFILTER_FL_KEY          "display_filter_list"
 
-/* About Ethereal window */
-#define MAX_ABOUT_MSG_LEN 2048
-
-/*
- * Keep a static pointer to the current "About Ethereal" window, if any, so
- * that if somebody tries to do "About Ethereal" while there's already an
- * "About Ethereal" window up, we just pop up the existing one, rather than
- * creating a new one.
- */
-static GtkWidget *about_ethereal_w;
-
-void
-about_ethereal( GtkWidget *w _U_, gpointer data _U_ )
-{
-  GtkWidget   *main_vb, *top_hb, *msg_label, *bbox, *ok_btn;
-  gchar        message[MAX_ABOUT_MSG_LEN];
-
-  if (about_ethereal_w != NULL) {
-    /* There's already an "About Ethereal" dialog box; reactivate it. */
-    reactivate_window(about_ethereal_w);
-    return;
-  }
-
-  /*
-   * XXX - use GtkDialog?  The GNOME 2.x GnomeAbout widget does.
-   * Should we use GtkDialog for simple_dialog() as well?  Or
-   * is the GTK+ 2.x GtkDialog appropriate but the 1.2[.x] one
-   * not?  (The GNOME 1.x GnomeAbout widget uses GnomeDialog.)
-   */
-  about_ethereal_w = dlg_window_new("About Ethereal");
-  SIGNAL_CONNECT(about_ethereal_w, "destroy", about_ethereal_destroy_cb, NULL);
-  gtk_container_border_width(GTK_CONTAINER(about_ethereal_w), 7);
-
-  /* Container for our rows */
-  main_vb = gtk_vbox_new(FALSE, 5);
-  gtk_container_border_width(GTK_CONTAINER(main_vb), 5);
-  gtk_container_add(GTK_CONTAINER(about_ethereal_w), main_vb);
-  gtk_widget_show(main_vb);
-
-  /* Top row: Message text */
-  top_hb = gtk_hbox_new(FALSE, 10);
-  gtk_container_add(GTK_CONTAINER(main_vb), top_hb);
-  gtk_widget_show(top_hb);
-
-  /* Construct the message string */
-  g_snprintf(message, MAX_ABOUT_MSG_LEN,
-          "Ethereal - Network Protocol Analyzer\n\n"
-          
-          "Version " VERSION
-#ifdef CVSVERSION
-          " (" CVSVERSION ")"
-#endif
-          " (C) 1998-2004 Gerald Combs <gerald@ethereal.com>\n\n"
-
-       "%s\n"
-       "%s\n\n"
-
-       "Ethereal is Open Source software released under the GNU General Public License.\n\n"
-
-          "Check the man page for complete documentation and\n"
-          "for the list of contributors.\n\n"
-
-          "See http://www.ethereal.com for more information.",
-           comp_info_str->str, runtime_info_str->str);
-
-  msg_label = gtk_label_new(message);
-  gtk_label_set_justify(GTK_LABEL(msg_label), GTK_JUSTIFY_FILL);
-  gtk_container_add(GTK_CONTAINER(top_hb), msg_label);
-  gtk_widget_show(msg_label);
-
-  /* Button row */
-  bbox = dlg_button_row_new(GTK_STOCK_OK, NULL);
-  gtk_container_add(GTK_CONTAINER(main_vb), bbox);
-  gtk_widget_show(bbox);
-
-  ok_btn = OBJECT_GET_DATA(bbox, GTK_STOCK_OK);
-  SIGNAL_CONNECT_OBJECT(ok_btn, "clicked", gtk_widget_destroy,
-                        about_ethereal_w);
-  gtk_widget_grab_default(ok_btn);
-
-  /* Catch the "key_press_event" signal in the window, so that we can catch
-     the ESC key being pressed and act as if the "Cancel" button had
-     been selected. */
-  dlg_set_cancel(about_ethereal_w, ok_btn);
-
-  gtk_widget_show(about_ethereal_w);
-}
-
-static void
-about_ethereal_destroy_cb(GtkWidget *win _U_, gpointer user_data _U_)
-{
-  /* Note that we no longer have an "About Ethereal" dialog box. */
-  about_ethereal_w = NULL;
-}
-
-#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. */
-       g_assert(m_r_font && m_b_font);
-       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 (cfile.finfo_selected) {
-       header_field_info       *hfinfo;
-       guint32                 framenum;
-
-       hfinfo = cfile.finfo_selected->hfinfo;
-       g_assert(hfinfo);
-       if (hfinfo->type == FT_FRAMENUM) {
-           framenum = fvalue_get_integer(&cfile.finfo_selected->value);
-           if (framenum != 0)
-               goto_frame(&cfile, framenum);
-       }
-    }
-}
-
-void
-goto_top_frame_cb(GtkWidget *w _U_, gpointer d _U_)
-{
-    goto_top_frame(&cfile);
-}
-
-void
-goto_bottom_frame_cb(GtkWidget *w _U_, gpointer d _U_)
-{
-    goto_bottom_frame(&cfile);
-}
-
-
-void
-view_zoom_in_cb(GtkWidget *w _U_, gpointer d _U_)
-{
-    gint save_gui_zoom_level;
-
-    save_gui_zoom_level = recent.gui_zoom_level;
-    recent.gui_zoom_level++;
-    switch (font_apply()) {
-
-    case FA_SUCCESS:
-        break;
-
-    case FA_FONT_NOT_RESIZEABLE:
-        /* "font_apply()" popped up an alert box. */
-        recent.gui_zoom_level = save_gui_zoom_level;   /* undo zoom */
-        break;
-
-    case FA_FONT_NOT_AVAILABLE:
-        /* We assume this means that the specified size isn't available. */
-        simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
-            "Your current font isn't available in the next larger size.\n");
-        recent.gui_zoom_level = save_gui_zoom_level;   /* undo zoom */
-        break;
-    }
-}
-
-void
-view_zoom_out_cb(GtkWidget *w _U_, gpointer d _U_)
-{
-    gint save_gui_zoom_level;
-
-    save_gui_zoom_level = recent.gui_zoom_level;
-    recent.gui_zoom_level--;
-    switch (font_apply()) {
-
-    case FA_SUCCESS:
-        break;
-
-    case FA_FONT_NOT_RESIZEABLE:
-        /* "font_apply()" popped up an alert box. */
-        recent.gui_zoom_level = save_gui_zoom_level;   /* undo zoom */
-        break;
-
-    case FA_FONT_NOT_AVAILABLE:
-        /* We assume this means that the specified size isn't available. */
-        simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
-            "Your current font isn't available in the next smaller size.\n");
-        recent.gui_zoom_level = save_gui_zoom_level;   /* undo zoom */
-        break;
-    }
-}
-
-void
-view_zoom_100_cb(GtkWidget *w _U_, gpointer d _U_)
-{
-    gint save_gui_zoom_level;
-
-    save_gui_zoom_level = recent.gui_zoom_level;
-    recent.gui_zoom_level = 0;
-    switch (font_apply()) {
-
-    case FA_SUCCESS:
-        break;
-
-    case FA_FONT_NOT_RESIZEABLE:
-        /* "font_apply()" popped up an alert box. */
-        recent.gui_zoom_level = save_gui_zoom_level;   /* undo zoom */
-        break;
-
-    case FA_FONT_NOT_AVAILABLE:
-        /* We assume this means that the specified size isn't available.
-           XXX - this "shouldn't happen". */
-        simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
-            "Your current font couldn't be reloaded at the size you selected.\n");
-        recent.gui_zoom_level = save_gui_zoom_level;   /* undo zoom */
-        break;
-    }
-}
 
 
 /* Match selected byte pattern */
@@ -484,113 +277,109 @@ match_selected_cb_do(gpointer data, int action, gchar *text)
 }
 
 void
-match_selected_cb_replace_ptree(GtkWidget *w, gpointer data)
+match_selected_ptree_cb(GtkWidget *w, gpointer data, MATCH_SELECTED_E action)
 {
     if (cfile.finfo_selected)
        match_selected_cb_do((data ? data : w),
-           MATCH_SELECTED_REPLACE|MATCH_SELECTED_APPLY_NOW,
+           action,
            proto_construct_dfilter_string(cfile.finfo_selected, cfile.edt));
 }
 
-void
-match_selected_cb_and_ptree(GtkWidget *w, gpointer data)
-{
-    if (cfile.finfo_selected)
-       match_selected_cb_do((data ? data : w),
-           MATCH_SELECTED_AND|MATCH_SELECTED_APPLY_NOW,
-           proto_construct_dfilter_string(cfile.finfo_selected, cfile.edt));
-}
 
-void
-match_selected_cb_or_ptree(GtkWidget *w, gpointer data)
+static void selected_ptree_info_answered_cb(gpointer dialog _U_, gint btn, gpointer data)
 {
-    if (cfile.finfo_selected)
-       match_selected_cb_do((data ? data : w),
-           MATCH_SELECTED_OR|MATCH_SELECTED_APPLY_NOW,
-           proto_construct_dfilter_string(cfile.finfo_selected, cfile.edt));
-}
+    gchar *selected_proto_url;
+    gchar *proto_abbrev = data;
 
-void
-match_selected_cb_not_ptree(GtkWidget *w, gpointer data)
-{
-    if (cfile.finfo_selected)
-       match_selected_cb_do((data ? data : w),
-           MATCH_SELECTED_NOT|MATCH_SELECTED_APPLY_NOW,
-           proto_construct_dfilter_string(cfile.finfo_selected, cfile.edt));
-}
 
-void
-match_selected_cb_and_ptree_not(GtkWidget *w, gpointer data)
-{
-    if (cfile.finfo_selected)
-       match_selected_cb_do((data ? data : w),
-           MATCH_SELECTED_AND_NOT|MATCH_SELECTED_APPLY_NOW,
-           proto_construct_dfilter_string(cfile.finfo_selected, cfile.edt));
+    switch(btn) {
+    case(ESD_BTN_OK):
+        if (cfile.finfo_selected) {
+            /* open wiki page using the protocol abbreviation */
+            selected_proto_url = g_strdup_printf("http://wiki.ethereal.com/Protocols/%s", proto_abbrev);
+            browser_open_url(selected_proto_url);
+            g_free(selected_proto_url);
+        }
+        break;
+    case(ESD_BTN_CANCEL):
+        break;
+    default:
+        g_assert_not_reached();
+    }
 }
 
-void
-match_selected_cb_or_ptree_not(GtkWidget *w, gpointer data)
-{
-    if (cfile.finfo_selected)
-       match_selected_cb_do((data ? data : w),
-           MATCH_SELECTED_OR_NOT,
-           proto_construct_dfilter_string(cfile.finfo_selected, cfile.edt));
-}
 
-void
-prepare_selected_cb_replace_ptree(GtkWidget *w, gpointer data)
+void 
+selected_ptree_info_cb(GtkWidget *widget _U_, gpointer data _U_)
 {
-    if (cfile.finfo_selected)
-       match_selected_cb_do((data ? data : w),
-           MATCH_SELECTED_REPLACE,
-           proto_construct_dfilter_string(cfile.finfo_selected, cfile.edt));
-}
+    int field_id;
+    gchar *proto_abbrev;
+    gpointer  dialog;
 
-void
-prepare_selected_cb_and_ptree(GtkWidget *w, gpointer data)
-{
-    if (cfile.finfo_selected)
-       match_selected_cb_do((data ? data : w),
-           MATCH_SELECTED_AND,
-           proto_construct_dfilter_string(cfile.finfo_selected, cfile.edt));
-}
 
-void
-prepare_selected_cb_or_ptree(GtkWidget *w, gpointer data)
-{
-    if (cfile.finfo_selected)
-       match_selected_cb_do((data ? data : w),
-           MATCH_SELECTED_OR,
-           proto_construct_dfilter_string(cfile.finfo_selected, cfile.edt));
-}
+    if (cfile.finfo_selected) {
+        /* convert selected field to protocol abbreviation */
+        /* XXX - could this conversion be simplified? */
+        field_id = cfile.finfo_selected->hfinfo->id;
+        /* if the selected field isn't a protocol, get it's parent */
+        if(!proto_registrar_is_protocol(field_id)) {
+            field_id = proto_registrar_get_parent(cfile.finfo_selected->hfinfo->id);
+        }
 
-void
-prepare_selected_cb_not_ptree(GtkWidget *w, gpointer data)
-{
-    if (cfile.finfo_selected)
-       match_selected_cb_do((data ? data : w),
-           MATCH_SELECTED_NOT,
-           proto_construct_dfilter_string(cfile.finfo_selected, cfile.edt));
+        proto_abbrev = proto_registrar_get_abbrev(field_id);
+
+        /* ask the user if the wiki page really should be opened */
+        dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_OK_CANCEL,
+                    PRIMARY_TEXT_START "Open Ethereal Wiki page of protocol \"%s\"?" PRIMARY_TEXT_END "\n"
+                    "\n"
+                    "This will open the \"%s\" related Ethereal Wiki page in your Web browser.\n"
+                    "\n"
+                    "The Ethereal Wiki is a collaborative approach to provide information\n"
+                    "about Ethereal in several ways (not limited to protocol specifics).\n"
+                    "\n"
+                    "This Wiki is new, so the page of the selected protocol\n"
+                    "may not exist and/or may not contain valuable information.\n"
+                    "\n"
+                    "As everyone can edit the Wiki and add new content (or extend existing),\n"
+                    "you are encouraged to add information if you can.\n"
+                    "\n"
+                    "Hint 1: If you are new to wiki editing, try out editing the Sandbox first!\n"
+                    "\n"
+                    "Hint 2: If you want to add a new protocol page, you should use the ProtocolTemplate,\n"
+                    "which will save you a lot of editing and will give a consistent look over the pages.",
+                    proto_abbrev, proto_abbrev);
+        simple_dialog_set_cb(dialog, selected_ptree_info_answered_cb, proto_abbrev);
+    }
 }
 
-void
-prepare_selected_cb_and_ptree_not(GtkWidget *w, gpointer data)
-{
-    if (cfile.finfo_selected)
-       match_selected_cb_do((data ? data : w),
-           MATCH_SELECTED_AND_NOT,
-           proto_construct_dfilter_string(cfile.finfo_selected, cfile.edt));
-}
 
-void
-prepare_selected_cb_or_ptree_not(GtkWidget *w, gpointer data)
+void 
+selected_ptree_ref_cb(GtkWidget *widget _U_, gpointer data _U_)
 {
-    if (cfile.finfo_selected)
-       match_selected_cb_do((data ? data : w),
-           MATCH_SELECTED_OR_NOT,
-           proto_construct_dfilter_string(cfile.finfo_selected, cfile.edt));
+    int field_id;
+    gchar *proto_abbrev;
+    gchar *selected_proto_url;
+
+
+    if (cfile.finfo_selected) {
+        /* convert selected field to protocol abbreviation */
+        /* XXX - could this conversion be simplified? */
+        field_id = cfile.finfo_selected->hfinfo->id;
+        /* if the selected field isn't a protocol, get it's parent */
+        if(!proto_registrar_is_protocol(field_id)) {
+            field_id = proto_registrar_get_parent(cfile.finfo_selected->hfinfo->id);
+        }
+
+        proto_abbrev = proto_registrar_get_abbrev(field_id);
+
+        /* open reference page using the protocol abbreviation */
+        selected_proto_url = g_strdup_printf("http://www.ethereal.com/docs/dfref/%c/%s", proto_abbrev[0], proto_abbrev);
+        browser_open_url(selected_proto_url);
+        g_free(selected_proto_url);
+    }
 }
 
+
 static gchar *
 get_text_from_packet_list(gpointer data)
 {
@@ -632,104 +421,17 @@ get_text_from_packet_list(gpointer data)
 }
 
 void
-match_selected_cb_replace_plist(GtkWidget *w _U_, gpointer data)
-{
-    match_selected_cb_do(data,
-        MATCH_SELECTED_REPLACE|MATCH_SELECTED_APPLY_NOW,
-        get_text_from_packet_list(data));
-}
-
-void
-match_selected_cb_and_plist(GtkWidget *w _U_, gpointer data)
+match_selected_plist_cb(GtkWidget *w _U_, gpointer data, MATCH_SELECTED_E action)
 {
     match_selected_cb_do(data,
-        MATCH_SELECTED_AND|MATCH_SELECTED_APPLY_NOW,
+        action,
         get_text_from_packet_list(data));
 }
 
-void
-match_selected_cb_or_plist(GtkWidget *w _U_, gpointer data)
-{
-    match_selected_cb_do(data,
-        MATCH_SELECTED_OR|MATCH_SELECTED_APPLY_NOW,
-        get_text_from_packet_list(data));
-}
 
-void
-match_selected_cb_not_plist(GtkWidget *w _U_, gpointer data)
-{
-    match_selected_cb_do(data,
-        MATCH_SELECTED_NOT|MATCH_SELECTED_APPLY_NOW,
-        get_text_from_packet_list(data));
-}
 
-void
-match_selected_cb_and_plist_not(GtkWidget *w _U_, gpointer data)
-{
-    match_selected_cb_do(data,
-        MATCH_SELECTED_AND_NOT|MATCH_SELECTED_APPLY_NOW,
-        get_text_from_packet_list(data));
-}
-
-void
-match_selected_cb_or_plist_not(GtkWidget *w _U_, gpointer data)
-{
-    match_selected_cb_do(data,
-        MATCH_SELECTED_OR_NOT|MATCH_SELECTED_APPLY_NOW,
-        get_text_from_packet_list(data));
-}
-
-void
-prepare_selected_cb_replace_plist(GtkWidget *w _U_, gpointer data)
-{
-    match_selected_cb_do(data,
-        MATCH_SELECTED_REPLACE,
-        get_text_from_packet_list(data));
-}
-
-void
-prepare_selected_cb_and_plist(GtkWidget *w _U_, gpointer data)
-{
-    match_selected_cb_do(data,
-        MATCH_SELECTED_AND,
-        get_text_from_packet_list(data));
-}
-
-void
-prepare_selected_cb_or_plist(GtkWidget *w _U_, gpointer data)
-{
-    match_selected_cb_do(data,
-        MATCH_SELECTED_OR,
-        get_text_from_packet_list(data));
-}
-
-void
-prepare_selected_cb_not_plist(GtkWidget *w _U_, gpointer data)
-{
-    match_selected_cb_do(data,
-        MATCH_SELECTED_NOT,
-        get_text_from_packet_list(data));
-}
-
-void
-prepare_selected_cb_and_plist_not(GtkWidget *w _U_, gpointer data)
-{
-    match_selected_cb_do(data,
-        MATCH_SELECTED_AND_NOT,
-        get_text_from_packet_list(data));
-}
-
-void
-prepare_selected_cb_or_plist_not(GtkWidget *w _U_, gpointer data)
-{
-    match_selected_cb_do(data,
-        MATCH_SELECTED_OR_NOT,
-        get_text_from_packet_list(data));
-}
-
-
-/* XXX: use a preference for this setting! */
-static guint dfilter_combo_max_recent = 10;
+/* XXX: use a preference for this setting! */
+static guint dfilter_combo_max_recent = 10;
 
 /* add a display filter to the combo box */
 /* Note: a new filter string will replace an old identical one */
@@ -807,7 +509,7 @@ dfilter_combo_add_recent(gchar *s) {
 }
 
 
-/* call filter_packets() and add this filter string to the recent filter list */
+/* call cf_filter_packets() and add this filter string to the recent filter list */
 gboolean
 main_filter_packets(capture_file *cf, const gchar *dftext, gboolean force)
 {
@@ -817,14 +519,15 @@ main_filter_packets(capture_file *cf, const gchar *dftext, gboolean force)
   gboolean   add_filter = TRUE;
   gboolean   free_filter = TRUE;
   char      *s;
-  gboolean   filter_packets_ret;
+  cf_status_t cf_status;
 
   s = g_strdup(dftext);
 
   /* 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. */
-  if ((filter_packets_ret = filter_packets(cf, s, force))) {
+  cf_status = cf_filter_packets(cf, s, force);
+  if (cf_status == CF_OK) {
     li = g_list_first(filter_list);
     while (li) {
       if (li->data && strcmp(s, li->data) == 0)
@@ -848,7 +551,7 @@ main_filter_packets(capture_file *cf, const gchar *dftext, gboolean force)
   if (free_filter)
     g_free(s);
 
-  return filter_packets_ret;
+  return (cf_status == CF_OK);
 }
 
 
@@ -886,19 +589,15 @@ set_frame_reftime(gboolean set, frame_data *frame, gint row) {
   } else {
     frame->flags.ref_time=0;
   }
-  reftime_packets(&cfile);
+  cf_reftime_packets(&cfile);
 }
 
-/* 0: toggle ref time status for the selected frame 
- * 1: find next ref time frame
- * 2: find previous reftime frame
- */
 void 
-reftime_frame_cb(GtkWidget *w _U_, gpointer data _U_, guint action)
+reftime_frame_cb(GtkWidget *w _U_, gpointer data _U_, REFTIME_ACTION_E action)
 {
 
   switch(action){
-  case 0: /* toggle ref frame */
+  case REFTIME_TOGGLE:
     if (cfile.current_frame) {
       /* XXX hum, should better have a "cfile->current_row" here ... */
       set_frame_reftime(!cfile.current_frame->flags.ref_time,
@@ -906,10 +605,10 @@ reftime_frame_cb(GtkWidget *w _U_, gpointer data _U_, guint action)
                     packet_list_find_row_from_data(cfile.current_frame));
     }
     break;
-  case 1: /* find next ref frame */
+  case REFTIME_FIND_NEXT:
     find_previous_next_frame_with_filter("frame.ref_time", FALSE);
     break;
-  case 2: /* find previous ref frame */
+  case REFTIME_FIND_PREV:
     find_previous_next_frame_with_filter("frame.ref_time", TRUE);
     break;
   }
@@ -953,7 +652,7 @@ tree_view_selection_changed_cb(GtkTreeSelection *sel, gpointer user_data _U_)
         if (byte_data == NULL)
             return;    /* none */
 
-        unselect_field(&cfile);
+        cf_unselect_field(&cfile);
         packet_hex_print(GTK_TEXT_VIEW(byte_view), byte_data,
                          cfile.current_frame, NULL, byte_len);
         return;
@@ -1050,7 +749,7 @@ tree_view_unselect_row_cb(GtkCTree *ctree _U_, GList *node _U_, gint column _U_,
        if (data == NULL)
                return; /* none */
 
-       unselect_field(&cfile);
+       cf_unselect_field(&cfile);
        packet_hex_print(GTK_TEXT(byte_view), data, cfile.current_frame,
                NULL, len);
 }
@@ -1158,6 +857,13 @@ void packets_bar_update(void)
     }
 }
 
+void
+main_set_for_capture_file(gboolean have_capture_file_in)
+{
+    have_capture_file = have_capture_file_in;
+
+    main_widgets_show_or_hide();
+}
 
 gboolean
 main_do_quit(void)
@@ -1190,7 +896,7 @@ main_do_quit(void)
 
 #ifdef HAVE_LIBPCAP
        /* Nuke any child capture in progress. */
-       kill_capture_child();
+       capture_kill_child(capture_opts);
 #endif
 
        /* Are we in the middle of reading a capture? */
@@ -1243,114 +949,100 @@ main_window_delete_event_cb(GtkWidget *widget _U_, GdkEvent *event _U_, gpointer
 {
   gpointer dialog;
 
-  if((cfile.state != FILE_CLOSED) && !cfile.user_saved) {
+  if((cfile.state != FILE_CLOSED) && !cfile.user_saved && prefs.gui_ask_unsaved) {
+#if GTK_MAJOR_VERSION >= 2
+    gtk_window_present(GTK_WINDOW(top_level));
+#endif
     /* user didn't saved his current file, ask him */
-    dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_YES_NO_CANCEL,
+    dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_SAVE_DONTSAVE_CANCEL,
                 PRIMARY_TEXT_START "Save capture file before program quit?" PRIMARY_TEXT_END "\n\n"
                 "If you quit the program without saving, your capture data will be discarded.");
     simple_dialog_set_cb(dialog, file_quit_answered_cb, NULL);
     return TRUE;
   } else {
     /* unchanged file, just exit */
-       /* "main_do_quit()" indicates whether the main window should be deleted. */
-       return main_do_quit();
+    /* "main_do_quit()" indicates whether the main window should be deleted. */
+    return main_do_quit();
   }
 }
 
+
+
 static void
-main_load_window_geometry(GtkWidget *widget
-#if GTK_MAJOR_VERSION < 2
-       _U_
-#endif
-)
-{
-    /* as we now have the geometry from the recent file, set it */
-    if (prefs.gui_geometry_save_position) {
-        gtk_widget_set_uposition(GTK_WIDGET(top_level),
-                                 recent.gui_geometry_main_x,
-                                 recent.gui_geometry_main_y);
-    }
-    if (prefs.gui_geometry_save_size) {
-        WIDGET_SET_SIZE(top_level, 
-                                recent.gui_geometry_main_width,
-                                recent.gui_geometry_main_height);
+main_load_window_geometry(GtkWidget *widget)
+{
+    window_geometry_t geom;
+
+    geom.set_pos        = prefs.gui_geometry_save_position;
+    geom.x              = recent.gui_geometry_main_x;
+    geom.y              = recent.gui_geometry_main_y;
+    geom.set_size       = prefs.gui_geometry_save_size;
+    if (recent.gui_geometry_main_width > 0 &&
+        recent.gui_geometry_main_height > 0) {
+        geom.width          = recent.gui_geometry_main_width;
+        geom.height         = recent.gui_geometry_main_height;
+        geom.set_maximized  = prefs.gui_geometry_save_maximized;
     } else {
-        WIDGET_SET_SIZE(top_level, DEF_WIDTH, -1);
+        /* We assume this means the width and height weren't set in
+           the "recent" file (or that there is no "recent" file),
+           and weren't set to a default value, so we don't set the
+           size.  (The "recent" file code rejects non-positive width
+           and height values.) */
+       geom.set_size = FALSE;
     }
+    geom.maximized      = recent.gui_geometry_main_maximized;
+
+    window_set_geometry(widget, &geom);
+
 #if GTK_MAJOR_VERSION >= 2
-    if(prefs.gui_geometry_save_maximized) {
-        if (recent.gui_geometry_main_maximized) {
-            gdk_window_maximize(widget->window);
-        } else {
-            gdk_window_unmaximize(widget->window);
-        }
-    }
+    /* XXX - rename recent settings? */
+    if (recent.gui_geometry_main_upper_pane)
+        gtk_paned_set_position(GTK_PANED(main_first_pane),  recent.gui_geometry_main_upper_pane);
+    if (recent.gui_geometry_main_lower_pane)
+        gtk_paned_set_position(GTK_PANED(main_second_pane), recent.gui_geometry_main_lower_pane);
+    if (recent.gui_geometry_status_pane)
+        gtk_paned_set_position(GTK_PANED(status_pane),      recent.gui_geometry_status_pane);
 #endif
 }
 
+
 static void
 main_save_window_geometry(GtkWidget *widget)
 {
-       gint desk_x, desk_y;
-#if GTK_MAJOR_VERSION >= 2
-    GdkWindowState state;
-#endif
-
-       /* Try to grab our geometry.
-
-          GTK+ provides two routines to get a window's position relative
-          to the X root window.  If I understand the documentation correctly,
-          gdk_window_get_deskrelative_origin applies mainly to Enlightenment
-          and gdk_window_get_root_origin applies for all other WMs.
+    window_geometry_t geom;
 
-          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
-       http://www.gtk.org/faq/#AEN606
-    */
+    window_get_geometry(widget, &geom);
 
     if (prefs.gui_geometry_save_position) {
-           gdk_window_get_root_origin(widget->window, 
-            &recent.gui_geometry_main_x, 
-            &recent.gui_geometry_main_y);
-           if (gdk_window_get_deskrelative_origin(widget->window,
-                                   &desk_x, &desk_y)) {
-                   if (desk_x <= recent.gui_geometry_main_x && 
-                desk_y <= recent.gui_geometry_main_y)
-            {
-                           recent.gui_geometry_main_x = desk_x;
-                           recent.gui_geometry_main_y = desk_y;
-                   }
-           }
+        recent.gui_geometry_main_x = geom.x;
+           recent.gui_geometry_main_y = geom.y;
     }
 
     if (prefs.gui_geometry_save_size) {
-           /* XXX - Is this the "approved" method? */
-           gdk_window_get_size(widget->window, 
-            &recent.gui_geometry_main_width, 
-            &recent.gui_geometry_main_height);
+        recent.gui_geometry_main_width  = geom.width, 
+        recent.gui_geometry_main_height = geom.height;
     }
 
 #if GTK_MAJOR_VERSION >= 2
     if(prefs.gui_geometry_save_maximized) {
-        state = gdk_window_get_state(widget->window);
-        recent.gui_geometry_main_maximized = (state == GDK_WINDOW_STATE_MAXIMIZED);
+        recent.gui_geometry_main_maximized = geom.maximized;
     }
+
+    recent.gui_geometry_main_upper_pane     = gtk_paned_get_position(GTK_PANED(main_first_pane));
+    recent.gui_geometry_main_lower_pane     = gtk_paned_get_position(GTK_PANED(main_second_pane));
+    recent.gui_geometry_status_pane         = gtk_paned_get_position(GTK_PANED(status_pane));
 #endif
 }
 
 static void file_quit_answered_cb(gpointer dialog _U_, gint btn, gpointer data _U_)
 {
     switch(btn) {
-    case(ESD_BTN_YES):
+    case(ESD_BTN_SAVE):
         /* save file first */
         file_save_as_cmd(after_save_exit, NULL);
         break;
-    case(ESD_BTN_NO):
-       main_do_quit();
+    case(ESD_BTN_DONT_SAVE):
+        main_do_quit();
         break;
     case(ESD_BTN_CANCEL):
         break;
@@ -1364,15 +1056,15 @@ file_quit_cmd_cb(GtkWidget *widget _U_, gpointer data _U_)
 {
   gpointer dialog;
 
-  if((cfile.state != FILE_CLOSED) && !cfile.user_saved) {
+  if((cfile.state != FILE_CLOSED) && !cfile.user_saved && prefs.gui_ask_unsaved) {
     /* user didn't saved his current file, ask him */
-    dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_YES_NO_CANCEL,
+    dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_SAVE_DONTSAVE_CANCEL,
                 PRIMARY_TEXT_START "Save capture file before program quit?" PRIMARY_TEXT_END "\n\n"
                 "If you quit the program without saving, your capture data will be discarded.");
     simple_dialog_set_cb(dialog, file_quit_answered_cb, NULL);
   } else {
     /* unchanged file, just exit */
-       main_do_quit();
+    main_do_quit();
   }
 }
 
@@ -1384,10 +1076,10 @@ print_usage(gboolean print_ver) {
   if (print_ver) {
     output = stdout;
     fprintf(output, "This is GNU " PACKAGE " " VERSION
-#ifdef CVSVERSION
-       " (" CVSVERSION ")"
+#ifdef SVNVERSION
+       " (" SVNVERSION ")"
 #endif
-       "\n%s\n%s\n",
+       "\n%s\n\n%s\n",
        comp_info_str->str, runtime_info_str->str);
   } else {
     output = stderr;
@@ -1416,15 +1108,15 @@ print_usage(gboolean print_ver) {
 static void
 show_version(void)
 {
-#ifdef WIN32
+#ifdef _WIN32
   create_console();
 #endif
 
   printf(PACKAGE " " VERSION
-#ifdef CVSVERSION
-      " (" CVSVERSION ")"
+#ifdef SVNVERSION
+      " (" SVNVERSION ")"
 #endif
-      "\n%s\n%s\n",
+      "\n%s\n\n%s\n",
       comp_info_str->str, runtime_info_str->str);
 }
 
@@ -1436,7 +1128,7 @@ get_natural_int(const char *string, const char *name)
 
   number = strtol(string, &p, 10);
   if (p == string || *p != '\0') {
-    fprintf(stderr, "ethereal: The specified %s \"%s\" is not a decimal number\n",
+    fprintf(stderr, "ethereal: The specified %s \"%s\" isn't a decimal number\n",
            name, string);
     exit(1);
   }
@@ -1469,105 +1161,7 @@ get_positive_int(const char *string, const char *name)
   return number;
 }
 
-#ifdef HAVE_LIBPCAP
-/*
- * Given a string of the form "<autostop criterion>:<value>", as might appear
- * as an argument to a "-a" option, parse it and set the criterion in
- * question.  Return an indication of whether it succeeded or failed
- * in some fashion.
- */
-static gboolean
-set_autostop_criterion(const char *autostoparg)
-{
-  gchar *p, *colonp;
-
-  colonp = strchr(autostoparg, ':');
-  if (colonp == NULL)
-    return FALSE;
-
-  p = colonp;
-  *p++ = '\0';
-
-  /*
-   * 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((guchar)*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;
-  }
-  if (strcmp(autostoparg,"duration") == 0) {
-    capture_opts.has_autostop_duration = TRUE;
-    capture_opts.autostop_duration = get_positive_int(p,"autostop duration");
-  } else if (strcmp(autostoparg,"filesize") == 0) {
-    capture_opts.has_autostop_filesize = TRUE;
-    capture_opts.autostop_filesize = get_positive_int(p,"autostop filesize");
-  } else {
-    return FALSE;
-  }
-  *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)
-{
-  gchar *p = NULL, *colonp;
-
-  colonp = strchr(arg, ':');
-
-  if (colonp != NULL) {
-    p = colonp;
-    *p++ = '\0';
-  }
-
-  capture_opts.ring_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((guchar)*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_file_duration = TRUE;
-  capture_opts.file_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
+#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
@@ -1614,14 +1208,14 @@ update_thread(gpointer data _U_)
 void
 protect_thread_critical_region(void)
 {
-#if ! defined WIN32 && GTK_MAJOR_VERSION >= 2 && defined USE_THREADS
+#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
+#if !defined(_WIN32) && GTK_MAJOR_VERSION >= 2 && defined USE_THREADS
     g_static_mutex_unlock(&update_thread_mutex);
 #endif
 }
@@ -1648,202 +1242,291 @@ register_ethereal_tap(char *cmd, void (*func)(char *arg))
 
 }
 
+/* Set the file name in the status line, in the name for the main window,
+   and in the name for the main window's icon. */
+static void
+set_display_filename(capture_file *cf)
+{
+  const gchar *name_ptr;
+  size_t       msg_len;
+  static const gchar done_fmt_nodrops[] = " File: %s %s %02u:%02u:%02u";
+  static const gchar done_fmt_drops[] = " File: %s %s %02u:%02u:%02u Drops: %u";
+  gchar       *done_msg;
+  gchar       *win_name_fmt = "%s - Ethereal";
+  gchar       *win_name;
+  gchar       *size_str;
+
+  name_ptr = cf_get_display_name(cf);
+       
+  if (!cf->is_tempfile) {
+    /* Add this filename to the list of recent files in the "Recent Files" submenu */
+    add_menu_recent_capture_file(cf->filename);
+  }
 
-enum { DND_TARGET_STRING, DND_TARGET_ROOTWIN, DND_TARGET_URL };
+  if (cf->f_len/1024/1024 > 10) {
+    size_str = g_strdup_printf("%ld MB", cf->f_len/1024/1024);
+  } else if (cf->f_len/1024 > 10) {
+    size_str = g_strdup_printf("%ld KB", cf->f_len/1024);
+  } else {
+    size_str = g_strdup_printf("%ld bytes", cf->f_len);
+  }
 
-void
-dnd_open_file_cmd(gpointer cf_name)
+  if (cf->drops_known) {
+    done_msg = g_strdup_printf(done_fmt_drops, name_ptr, size_str, 
+        cf->esec/3600, cf->esec%3600/60, cf->esec%60, cf->drops);
+  } else {
+    done_msg = g_strdup_printf(done_fmt_nodrops, name_ptr, size_str,
+        cf->esec/3600, cf->esec%3600/60, cf->esec%60);
+  }
+  statusbar_push_file_msg(done_msg);
+  g_free(done_msg);
+
+  msg_len = strlen(name_ptr) + strlen(win_name_fmt) + 1;
+  win_name = g_malloc(msg_len);
+  snprintf(win_name, msg_len, win_name_fmt, name_ptr);
+  set_main_window_name(win_name);
+  g_free(win_name);
+}
+
+
+static void
+main_cf_cb_file_closed(capture_file *cf)
 {
-       int       err;
+    /* Destroy all windows, which refer to the
+       capture file we're closing. */
+    destroy_cfile_wins();
 
-    
-    /* open and read the capture file (this will close an existing file) */
-       if ((err = cf_open(cf_name, FALSE, &cfile)) == 0) {
-               cf_read(&cfile);
-        add_menu_recent_capture_file(cf_name);
-       } else {
-               /* the capture file couldn't be read (doesn't exist, file format unknown, ...) */
-       }
+    /* Clear any file-related status bar messages.
+       XXX - should be "clear *ALL* file-related status bar messages;
+       will there ever be more than one on the stack? */
+    statusbar_pop_file_msg();
+
+    /* Restore the standard title bar message. */
+    set_main_window_name("The Ethereal Network Analyzer");
+
+    /* Disable all menu items that make sense only if you have a capture. */
+    set_menus_for_capture_file(FALSE);
+    set_menus_for_unsaved_capture_file(FALSE);
+    set_menus_for_captured_packets(FALSE);
+    set_menus_for_selected_packet(cf);
+    set_menus_for_capture_in_progress(FALSE);
+    set_menus_for_selected_tree_row(cf);
 
-    g_free(cf_name);
+    /* Set up main window for no capture file. */
+    main_set_for_capture_file(FALSE);
 }
 
-static void 
-dnd_open_file_answered_cb(gpointer dialog _U_, gint btn, gpointer data _U_)
+static void
+main_cf_cb_file_read_start(capture_file *cf)
 {
-    switch(btn) {
-    case(ESD_BTN_YES):
-        /* save file first */
-        file_save_as_cmd(after_save_open_dnd_file, data);
-        break;
-    case(ESD_BTN_NO):
-        cf_close(&cfile);
-        dnd_open_file_cmd(data);
-        break;
-    case(ESD_BTN_CANCEL):
-        g_free(data);
-        break;
-    default:
-        g_assert_not_reached();
-    }
+  const gchar *name_ptr;
+  gchar       *load_msg;
+
+  name_ptr = get_basename(cf->filename);
+
+  load_msg = g_strdup_printf(" Loading: %s", name_ptr);
+  statusbar_push_file_msg(load_msg);
+  g_free(load_msg);
 }
 
-static gchar *
-dnd_uri2filename(gchar *cf_name)
+static void
+main_cf_cb_file_read_finished(capture_file *cf)
 {
-    gchar     *src, *dest;
-    gint      ret;
-    guint     i;
-    gchar     esc[3];
+    statusbar_pop_file_msg();
+    set_display_filename(cf);
 
+    /* Enable menu items that make sense if you have a capture file you've
+     finished reading. */
+    set_menus_for_capture_file(TRUE);
+    set_menus_for_unsaved_capture_file(!cf->user_saved);
 
-    /*
-     * Remove URI header.
-     * On win32 (at least WinXP), this string looks like (UNC or local filename):
-     * file:////servername/sharename/dir1/dir2/capture-file.cap
-     * or
-     * file:///d:/dir1/dir2/capture-file.cap
-     * we have to remove the prefix to get a valid filename.
-     *
-     * On UNIX (at least KDE 3.0 Konqueror), this string looks like:
-     * file:/dir1/dir2/capture-file.cap
-     * we have to remove the file: to get a valid filename.
-     */ 
-    if (strncmp("file:////", cf_name, 9) == 0) {
-        /* now becoming: //servername/sharename/dir1/dir2/capture-file.cap */
-        cf_name += 7;
-    } else if (strncmp("file:///", cf_name, 8) == 0) {
-        /* now becoming: d:/dir1/dir2/capture-file.cap */
-        cf_name += 8;
-    } else if (strncmp("file:", cf_name, 5) == 0) {
-        /* now becoming: /dir1/dir2/capture-file.cap */
-        cf_name += 5;
-    }
+    /* Enable menu items that make sense if you have some captured packets. */
+    set_menus_for_captured_packets(TRUE);
+
+    /* Set up main window for a capture file. */
+    main_set_for_capture_file(TRUE);
+}
+
+#ifdef HAVE_LIBPCAP
+static void
+main_cf_cb_live_capture_prepare(capture_options *capture_opts)
+{
+    gchar *title;
 
-    /* 
-     * unescape the escaped URI characters (spaces, ...)
-     *
-     * we have to replace escaped chars to their equivalents, 
-     * e.g. %20 (always a two digit hexstring) -> ' '
-     * the percent character '%' is escaped be a double one "%%"
-     *
-     * we do this conversation "in place" as the result is always 
-     * equal or smaller in size.
-     */
-    src = cf_name;
-    dest = cf_name;
-    while (*src) {
-        if (*src == '%') {
-            src++;
-            if (*src == '%') {
-                /* this is an escaped '%' char (was: "%%") */
-                *dest = *src;
-                src++;
-                dest++;
-            } else {
-                /* convert escaped hexnumber to unscaped character */
-                esc[0] = src[0];
-                esc[1] = src[1];
-                esc[2] = '\0';
-                ret = sscanf(esc, "%x", &i);
-                if (ret == 1) {
-                    src+=2;
-                    *dest = (gchar) i;
-                    dest++;
-                } else {
-                    /* somethings wrong, just jump over that char
-                     * this will result in a wrong string, but we might get
-                     * user feedback and can fix it later ;-) */
-                    src++;
-                }
-            }
-        } else {
-            *dest = *src;
-            src++;
-            dest++;
-        }
-    }
-    *dest = '\0';
 
-    return cf_name;
+    title = g_strdup_printf("%s: Capturing - Ethereal",
+                            get_interface_descriptive_name(capture_opts->iface));
+    set_main_window_name(title);
+    g_free(title);
 }
 
-static void 
-dnd_data_received(GtkWidget *widget _U_, GdkDragContext *dc _U_, gint x _U_, gint y _U_, 
-GtkSelectionData *selection_data, guint info, guint t _U_, gpointer data _U_)
+static void
+main_cf_cb_live_capture_started(capture_options *capture_opts)
 {
-    gchar     *cf_name, *cf_name_ori;
-    gpointer  dialog;
+    gchar *capture_msg;
 
-    if (info == DND_TARGET_URL) {
-        /* DND_TARGET_URL on Win32:
-         * The selection_data->data is a single string, containing one or more URI's,
-         * seperated by CR/NL chars. The length of the whole field can be found 
-         * in the selection_data->length field. As we can't handle more than one 
-         * capture file at a time, we only try to load the first one. */
+    /* Disable menu items that make no sense if you're currently running
+       a capture. */
+    set_menus_for_capture_in_progress(TRUE);
 
-        /* XXX: how does this string look like on other platforms? */
+    /* Enable menu items that make sense if you have some captured
+       packets (yes, I know, we don't have any *yet*). */
+    set_menus_for_captured_packets(TRUE);
 
-        /* XXX: if more than one file is in the string, we might want to have 
-         * a dialog box asking to merge these files together? */
+    capture_msg = g_strdup_printf(" %s: <live capture in progress>", get_interface_descriptive_name(capture_opts->iface));
 
-        /* the name might not be zero terminated -> make a copy of it */
-        cf_name_ori = g_strndup((gchar *)selection_data->data, selection_data->length);
-        cf_name = cf_name_ori;
+    statusbar_push_file_msg(capture_msg);
 
-        /* replace trailing CR NL simply with zeroes */
-        g_strdelimit(cf_name, "\r\n", '\0');
+    g_free(capture_msg);
 
-        /* convert the URI to a local filename */
-        cf_name = dnd_uri2filename(cf_name);
+    /* Set up main window for a capture file. */
+    main_set_for_capture_file(TRUE);
+}
 
-        /* we need a clean name for later call to g_free() */
-        cf_name = strdup(cf_name);
-        g_free(cf_name_ori);
+static void
+main_cf_cb_live_capture_finished(capture_file *cf)
+{
+    /* Pop the "<live capture in progress>" message off the status bar. */
+    statusbar_pop_file_msg();
 
-        /* ask the user to save it's current capture file first */
-        if((cfile.state != FILE_CLOSED) && !cfile.user_saved) {
-            /* user didn't saved his current file, ask him */
-            dialog = simple_dialog(ESD_TYPE_CONFIRMATION,
-                        ESD_BTNS_YES_NO_CANCEL,
-                        PRIMARY_TEXT_START "Save capture file before opening a new one?" PRIMARY_TEXT_END "\n\n"
-                        "If you open a new capture file without saving, your current capture data will be discarded.");
-            simple_dialog_set_cb(dialog, dnd_open_file_answered_cb, cf_name);
-        } else {
-            /* unchanged file */
-            dnd_open_file_cmd(cf_name);
-        }
-    }
+    set_display_filename(cf);
+
+    /* Enable menu items that make sense if you're not currently running
+     a capture. */
+    set_menus_for_capture_in_progress(FALSE);
+
+    /* Enable menu items that make sense if you have a capture file
+     you've finished reading. */
+    set_menus_for_capture_file(TRUE);
+    set_menus_for_unsaved_capture_file(!cf->user_saved);
+
+    /* Set up main window for a capture file. */
+    main_set_for_capture_file(TRUE);
 }
+#endif
 
-static void 
-dnd_init(GtkWidget *w)
+static void
+main_cf_cb_packet_selected(gpointer data)
 {
-    /* we are only interested in the URI list containing filenames */
-    static GtkTargetEntry target_entry[] = {
-         /*{"STRING", 0, DND_TARGET_STRING},*/
-         /*{"text/plain", 0, DND_TARGET_STRING},*/
-         {"text/uri-list", 0, DND_TARGET_URL}
-    };
+    capture_file *cf = data;
+
+    /* Display the GUI protocol tree and hex dump.
+      XXX - why do we dump core if we call "proto_tree_draw()"
+      before calling "add_byte_views()"? */
+    add_main_byte_views(cf->edt);
+    main_proto_tree_draw(cf->edt->tree);
+
+    /* A packet is selected. */
+    set_menus_for_selected_packet(cf);
+}
+
+static void
+main_cf_cb_packet_unselected(capture_file *cf)
+{
+    /* Clear out the display of that packet. */
+    clear_tree_and_hex_views();
+
+    /* No packet is selected. */
+    set_menus_for_selected_packet(cf);
+}
+
+static void
+main_cf_cb_field_unselected(capture_file *cf)
+{
+    statusbar_pop_field_msg();
+    set_menus_for_selected_tree_row(cf);
+}
+
+static void
+main_cf_cb_file_safe_started(gchar * filename)
+{
+    const gchar  *name_ptr;
+    gchar        *save_msg;
+
+    name_ptr = get_basename(filename);
 
-    /* set this window as a dnd destination */
-    gtk_drag_dest_set(
-         w, GTK_DEST_DEFAULT_ALL, target_entry,
-         sizeof(target_entry) / sizeof(GtkTargetEntry),
-         (GdkDragAction)(GDK_ACTION_MOVE | GDK_ACTION_COPY) );
+    save_msg = g_strdup_printf(" Saving: %s...", name_ptr);
 
-    /* get notified, if some dnd coming in */
-    gtk_signal_connect(GTK_OBJECT(w), "drag_data_received",
-        GTK_SIGNAL_FUNC(dnd_data_received), NULL);
+    statusbar_push_file_msg(save_msg);
+    g_free(save_msg);
 }
 
+static void
+main_cf_cb_file_safe_finished(gpointer data _U_)
+{
+    /* Pop the "Saving:" message off the status bar. */
+    statusbar_pop_file_msg();
+}
+
+static void
+main_cf_cb_file_safe_failed(gpointer data _U_)
+{
+    /* Pop the "Saving:" message off the status bar. */
+    statusbar_pop_file_msg();
+}
+
+static void
+main_cf_cb_file_safe_reload_finished(gpointer data _U_)
+{
+    set_menus_for_unsaved_capture_file(FALSE);
+}
+
+void main_cf_callback(gint event, gpointer data, gpointer user_data _U_)
+{
+    switch(event) {
+    case(cf_cb_file_closed):
+        main_cf_cb_file_closed(data);
+        break;
+    case(cf_cb_file_read_start):
+        main_cf_cb_file_read_start(data);
+        break;
+    case(cf_cb_file_read_finished):
+        main_cf_cb_file_read_finished(data);
+        break;
+#ifdef HAVE_LIBPCAP
+    case(cf_cb_live_capture_prepare):
+        main_cf_cb_live_capture_prepare(data);
+        break;
+    case(cf_cb_live_capture_started):
+        main_cf_cb_live_capture_started(data);
+        break;
+    case(cf_cb_live_capture_finished):
+        main_cf_cb_live_capture_finished(data);
+        break;
+#endif
+    case(cf_cb_packet_selected):
+        main_cf_cb_packet_selected(data);
+        break;
+    case(cf_cb_packet_unselected):
+        main_cf_cb_packet_unselected(data);
+        break;
+    case(cf_cb_field_unselected):
+        main_cf_cb_field_unselected(data);
+        break;
+    case(cf_cb_file_safe_started):
+        main_cf_cb_file_safe_started(data);
+        break;
+    case(cf_cb_file_safe_finished):
+        main_cf_cb_file_safe_finished(data);
+        break;
+    case(cf_cb_file_safe_reload_finished):
+        main_cf_cb_file_safe_reload_finished(data);
+        break;
+    case(cf_cb_file_safe_failed):
+        main_cf_cb_file_safe_failed(data);
+        break;
+    default:
+        g_warning("main_cf_callback: event %u unknown", event);
+        g_assert_not_reached();
+    }
+}
 
 /* And now our feature presentation... [ fade to music ] */
 int
 main(int argc, char *argv[])
 {
 #ifdef HAVE_LIBPCAP
-  char                *command_name;
+  const char          *command_name;
 #endif
   char                *s;
   int                  i;
@@ -1851,9 +1534,9 @@ main(int argc, char *argv[])
   extern char         *optarg;
   gboolean             arg_error = FALSE;
 
-#ifdef WIN32
+#ifdef _WIN32
   WSADATA             wsaData;
-#endif  /* WIN32 */
+#endif  /* _WIN32 */
 
   char                *rf_path;
   int                  rf_open_errno;
@@ -1868,12 +1551,12 @@ main(int argc, char *argv[])
   int                  err;
 #ifdef HAVE_LIBPCAP
   gboolean             start_capture = FALSE;
-  gchar               *save_file = NULL;
   GList               *if_list;
   if_info_t           *if_info;
   GList               *lt_list, *lt_entry;
   data_link_info_t    *data_link_info;
   gchar                err_str[PCAP_ERRBUF_SIZE];
+  gchar               *cant_get_if_list_errstr;
   gboolean             stats_known;
   struct pcap_stat     stats;
 #else
@@ -1885,20 +1568,18 @@ 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
   ethereal_tap_list   *tli = NULL;
   gchar               *tap_opt = NULL;
+  GtkWidget           *splash_win = NULL;
 
-#define OPTSTRING_INIT "a:b:B:c:f:hi:klLm:nN:o:pP:Qr:R:Ss:t:T:w:vy:z:"
+#define OPTSTRING_INIT "a:b:B:c:f:Hhi:klLm:nN:o:pP:Qr:R:Ss:t:T:w:vy:z:"
 
 #ifdef HAVE_LIBPCAP
-#ifdef WIN32
+#ifdef _WIN32
 #define OPTSTRING_CHILD "W:Z:"
 #else
 #define OPTSTRING_CHILD "W:"
-#endif  /* WIN32 */
+#endif  /* _WIN32 */
 #else
 #define OPTSTRING_CHILD ""
 #endif  /* HAVE_LIBPCAP */
@@ -1906,9 +1587,26 @@ main(int argc, char *argv[])
   char optstring[sizeof(OPTSTRING_INIT) + sizeof(OPTSTRING_CHILD) - 1] =
     OPTSTRING_INIT;
 
+
+  /* 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. */
+  gtk_set_locale();
+
+  /* Let GTK get its args */
+  gtk_init (&argc, &argv);
+
+  cf_callback_add(main_cf_callback, NULL);
+
+#if GTK_MAJOR_VERSION < 2 && GTK_MINOR_VERSION < 3
+  /* initialize our GTK eth_clist_type */
+  init_eth_clist_type();
+#endif
+
   ethereal_path = argv[0];
 
-#ifdef WIN32
+#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.
 
@@ -1927,24 +1625,56 @@ main(int argc, char *argv[])
 #endif
 
 #ifdef HAVE_LIBPCAP
+  /* Set the initial values in the capture_opts. This might be overwritten 
+     by preference settings and then again by the command line parameters. */
+  capture_opts_init(capture_opts, &cfile);
+
   command_name = get_basename(ethereal_path);
   /* Set "capture_child" to indicate whether this is going to be a child
      process for a "-S" capture. */
-  capture_child = (strcmp(command_name, CHILD_NAME) == 0);
-  if (capture_child)
+  capture_opts->capture_child = (strcmp(command_name, CHILD_NAME) == 0);
+  if (capture_opts->capture_child) {
     strcat(optstring, OPTSTRING_CHILD);
+  }
 #endif
 
+  /* We want a splash screen only if we're not a child process */
+    /* We also want it only if we're not being run with "-G".
+       XXX - we also don't want it if we're being run with
+       "-h" or "-v", as those are options to run Ethereal and just
+       have it print stuff to the command line.  That would require
+       that we parse the argument list before putting up the splash
+       screen, which means we'd need to do so before reading the
+       preference files, as that could take enough time that we'd
+       want the splash screen up while we're doing that.  Unfortunately,
+       that means we'd have to queue up, for example, "-o" options,
+       so that we apply them *after* reading the preferences, as
+       they're supposed to override saved preferences. */
+  if ((argc < 2 || strcmp(argv[1], "-G") != 0)
+#ifdef HAVE_LIBPCAP
+      && !capture_opts->capture_child
+#endif
+      ) {
+    splash_win = splash_new("Loading Ethereal ...");
+  }
+
+  splash_update(splash_win, "Registering dissectors ...");
+
   /* Register all dissectors; we must do this before checking for the
      "-G" flag, as the "-G" flag dumps information 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);
+  epan_init(PLUGIN_DIR,register_all_protocols,register_all_protocol_handoffs,
+            failure_alert_box,open_failure_alert_box,read_failure_alert_box);
+
+  splash_update(splash_win, "Registering tap listeners ...");
 
   /* 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();
 
+  splash_update(splash_win, "Loading module preferences ...");
+
   /* Now register the preferences for any non-dissector modules.
      We must do that before we read the preferences as well. */
   prefs_register_modules();
@@ -1973,25 +1703,10 @@ main(int argc, char *argv[])
        to specify the information to dump;
 
        arguments after that will not be used. */
-  if (argc >= 2 && strcmp(argv[1], "-G") == 0) {
-    if (argc == 2)
-      proto_registrar_dump_fields();
-    else {
-      if (strcmp(argv[2], "fields") == 0)
-        proto_registrar_dump_fields();
-      else if (strcmp(argv[2], "protocols") == 0)
-        proto_registrar_dump_protocols();
-      else {
-        fprintf(stderr, "ethereal: Invalid \"%s\" option for -G flag\n",
-                argv[2]);
-        exit(1);
-      }
-    }
-    exit(0);
-  }
+  handle_dashG_option(argc, argv, "ethereal");
 
   /* 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
+#if !defined(_WIN32) && GTK_MAJOR_VERSION >= 2 && defined(G_THREADS_ENABLED) && defined USE_THREADS
   {
       GThread *ut;
       g_thread_init(NULL);
@@ -1999,52 +1714,55 @@ main(int argc, char *argv[])
       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 */
+#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 */
+#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. */
-  gtk_set_locale();
-
-  /* Let GTK get its args */
-  gtk_init (&argc, &argv);
+  splash_update(splash_win, "Loading configuration files ...");
 
   /* Read the preference files. */
   prefs = read_prefs(&gpf_open_errno, &gpf_read_errno, &gpf_path,
                      &pf_open_errno, &pf_read_errno, &pf_path);
+  if (gpf_path != NULL) {
+    if (gpf_open_errno != 0) {
+      simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
+        "Could not open global preferences file\n\"%s\": %s.", gpf_path,
+        strerror(gpf_open_errno));
+    }
+    if (gpf_read_errno != 0) {
+      simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
+        "I/O error reading global preferences file\n\"%s\": %s.", gpf_path,
+        strerror(gpf_read_errno));
+    }
+  }
+  if (pf_path != NULL) {
+    if (pf_open_errno != 0) {
+      simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
+        "Could not open your preferences file\n\"%s\": %s.", pf_path,
+        strerror(pf_open_errno));
+    }
+    if (pf_read_errno != 0) {
+      simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
+        "I/O error reading your preferences file\n\"%s\": %s.", pf_path,
+        strerror(pf_read_errno));
+    }
+    g_free(pf_path);
+    pf_path = NULL;
+  }
 
-#ifdef HAVE_LIBPCAP
-  capture_opts.has_snaplen = FALSE;
-  capture_opts.snaplen = MIN_PACKET_SIZE;
-  capture_opts.linktype = -1;
 #ifdef _WIN32
-  capture_opts.buffer_size = 1;
+  /* if the user wants a console to be always there, well, we should open one for him */
+  if (prefs->gui_console_open == console_open_always) {
+    create_console();
+  }
 #endif
 
-  capture_opts.has_autostop_packets = FALSE;
-  capture_opts.autostop_packets = 1;
-  capture_opts.has_autostop_duration = FALSE;
-  capture_opts.autostop_duration = 1;
-  capture_opts.has_autostop_filesize = FALSE;
-  capture_opts.autostop_filesize = 1;
-  capture_opts.has_autostop_files = FALSE;
-  capture_opts.autostop_files = 1;
-
-  capture_opts.multi_files_on = FALSE;
-  capture_opts.has_ring_num_files = TRUE;
-  capture_opts.ring_num_files = 2;
-  capture_opts.has_file_duration = FALSE;
-  capture_opts.file_duration = 1;
-
+#ifdef HAVE_LIBPCAP
   /* If this is a capture child process, it should pay no attention
      to the "prefs.capture_prom_mode" setting in the preferences file;
      it should do what the parent process tells it to do, and if
@@ -2052,41 +1770,78 @@ main(int argc, char *argv[])
      tell it so with a "-p" flag.
 
      Otherwise, set promiscuous mode from the preferences setting. */
-  if (capture_child)
-    capture_opts.promisc_mode = TRUE;
-  else
-    capture_opts.promisc_mode = prefs->capture_prom_mode;
-
-  /* Set "Update list of packets in real time" mode from the preferences
-     setting. */
-  capture_opts.sync_mode = prefs->capture_real_time;
+  /* the same applies to other preferences settings as well. */
+  if (capture_opts->capture_child) {
+    auto_scroll_live             = FALSE;
+  } else {
+    capture_opts->promisc_mode   = prefs->capture_prom_mode;
+    capture_opts->show_info      = prefs->capture_show_info;
+    capture_opts->sync_mode      = prefs->capture_real_time;
+    auto_scroll_live             = prefs->capture_auto_scroll;
+  }
 
-  /* And do the same for "Automatic scrolling in live capture" mode. */
-  auto_scroll_live = prefs->capture_auto_scroll;
-#endif
+#endif /* HAVE_LIBPCAP */
 
   /* Set the name resolution code's flags from the preferences. */
   g_resolv_flags = prefs->name_resolve;
 
   /* Read the capture filter file. */
   read_filter_list(CFILTER_LIST, &cf_path, &cf_open_errno);
+  if (cf_path != NULL) {
+      simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
+        "Could not open your capture filter file\n\"%s\": %s.", cf_path,
+        strerror(cf_open_errno));
+      g_free(cf_path);
+  }
 
   /* Read the display filter file. */
   read_filter_list(DFILTER_LIST, &df_path, &df_open_errno);
+  if (df_path != NULL) {
+      simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
+        "Could not open your display filter file\n\"%s\": %s.", df_path,
+        strerror(df_open_errno));
+      g_free(df_path);
+  }
 
   /* Read the disabled protocols file. */
   read_disabled_protos_list(&gdp_path, &gdp_open_errno, &gdp_read_errno,
                            &dp_path, &dp_open_errno, &dp_read_errno);
+  if (gdp_path != NULL) {
+    if (gdp_open_errno != 0) {
+      simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
+        "Could not open global disabled protocols file\n\"%s\": %s.",
+       gdp_path, strerror(gdp_open_errno));
+    }
+    if (gdp_read_errno != 0) {
+      simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
+        "I/O error reading global disabled protocols file\n\"%s\": %s.",
+       gdp_path, strerror(gdp_read_errno));
+    }
+    g_free(gdp_path);
+  }
+  if (dp_path != NULL) {
+    if (dp_open_errno != 0) {
+      simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
+        "Could not open your disabled protocols file\n\"%s\": %s.", dp_path,
+        strerror(dp_open_errno));
+    }
+    if (dp_read_errno != 0) {
+      simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
+        "I/O error reading your disabled protocols file\n\"%s\": %s.", dp_path,
+        strerror(dp_read_errno));
+    }
+    g_free(dp_path);
+  }
 
   init_cap_file(&cfile);
 
-#ifdef WIN32
+#ifdef _WIN32
   /* Load wpcap if possible. Do this before collecting the run-time version information */
   load_wpcap();
 
   /* Start windows sockets */
   WSAStartup( MAKEWORD( 1, 1 ), &wsaData );
-#endif  /* WIN32 */
+#endif  /* _WIN32 */
 
   /* Assemble the compile-time version information string */
   comp_info_str = g_string_new("Compiled ");
@@ -2109,72 +1864,48 @@ main(int argc, char *argv[])
   /* Now get our args */
   while ((opt = getopt(argc, argv, optstring)) != -1) {
     switch (opt) {
+      /*** capture option specific ***/
       case 'a':        /* autostop criteria */
+      case 'b':        /* Ringbuffer option */
+      case 'c':        /* Capture xxx packets */
+      case 'f':        /* capture filter */
+      case 'k':        /* Start capture immediately */
+      case 'H':        /* Hide capture info dialog box */
+      case 'i':        /* Use interface xxx */
+      case 'p':        /* Don't capture in promiscuous mode */
+      case 'Q':        /* Quit after capture (just capture to file) */
+      case 's':        /* Set the snapshot (capture) length */
+      case 'S':        /* "Sync" mode: used for following file ala tail -f */
+      case 'w':        /* Write to capture file xxx */
+      case 'y':        /* Set the pcap data link type */
+#ifdef _WIN32
+      /* Hidden option supporting Sync mode */
+      case 'Z':        /* Write to pipe FD XXX */
+#endif /* _WIN32 */
 #ifdef HAVE_LIBPCAP
-        if (set_autostop_criterion(optarg) == FALSE) {
-          fprintf(stderr, "ethereal: Invalid or unknown -a flag \"%s\"\n", optarg);
-          exit(1);
-        }
+        capture_opt_add(capture_opts, opt, optarg, &start_capture);
 #else
         capture_option_specified = TRUE;
         arg_error = TRUE;
 #endif
         break;
-      case 'b':        /* Ringbuffer option */
 #ifdef HAVE_LIBPCAP
-        capture_opts.multi_files_on = TRUE;
-        capture_opts.has_ring_num_files = TRUE;
-       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;
+      /* This is a hidden option supporting Sync mode, so we don't set
+       * the error flags for the user in the non-libpcap case.
+       */
+      case 'W':        /* Write to capture file FD xxx */
+        capture_opt_add(capture_opts, opt, optarg, &start_capture);
+       break;
 #endif
-        break;
+
+      /*** all non capture option specific ***/
       case 'B':        /* Byte view pane height */
         bv_size = get_positive_int(optarg, "byte view pane height");
         break;
-      case 'c':        /* Capture xxx packets */
-#ifdef HAVE_LIBPCAP
-        capture_opts.has_autostop_packets = TRUE;
-        capture_opts.autostop_packets = get_positive_int(optarg, "packet count");
-#else
-        capture_option_specified = TRUE;
-        arg_error = TRUE;
-#endif
-        break;
-      case 'f':
-#ifdef HAVE_LIBPCAP
-       if (cfile.cfilter)
-               g_free(cfile.cfilter);
-       cfile.cfilter = g_strdup(optarg);
-#else
-        capture_option_specified = TRUE;
-        arg_error = TRUE;
-#endif
-       break;
       case 'h':        /* Print help and exit */
        print_usage(TRUE);
        exit(0);
         break;
-      case 'i':        /* Use interface xxx */
-#ifdef HAVE_LIBPCAP
-        cfile.iface = g_strdup(optarg);
-#else
-        capture_option_specified = TRUE;
-        arg_error = TRUE;
-#endif
-        break;
-      case 'k':        /* Start capture immediately */
-#ifdef HAVE_LIBPCAP
-        start_capture = TRUE;
-#else
-        capture_option_specified = TRUE;
-        arg_error = TRUE;
-#endif
-        break;
       case 'l':        /* Automatic scrolling in live capture mode */
 #ifdef HAVE_LIBPCAP
         auto_scroll_live = TRUE;
@@ -2186,7 +1917,6 @@ main(int argc, char *argv[])
       case 'L':        /* Print list of link-layer types and exit */
 #ifdef HAVE_LIBPCAP
         list_link_layer_types = TRUE;
-        break;
 #else
         capture_option_specified = TRUE;
         arg_error = TRUE;
@@ -2226,26 +1956,9 @@ main(int argc, char *argv[])
           break;
         }
         break;
-      case 'p':        /* Don't capture in promiscuous mode */
-#ifdef HAVE_LIBPCAP
-       capture_opts.promisc_mode = FALSE;
-#else
-        capture_option_specified = TRUE;
-        arg_error = TRUE;
-#endif
-       break;
       case 'P':        /* Packet list pane height */
         pl_size = get_positive_int(optarg, "packet list pane height");
         break;
-      case 'Q':        /* Quit after capture (just capture to file) */
-#ifdef HAVE_LIBPCAP
-        quit_after_cap  = TRUE;
-        start_capture   = TRUE;  /*** -Q implies -k !! ***/
-#else
-        capture_option_specified = TRUE;
-        arg_error = TRUE;
-#endif
-        break;
       case 'r':        /* Read capture file xxx */
        /* We may set "last_open_dir" to "cf_name", and if we change
           "last_open_dir" later, we free the old value, so we have to
@@ -2255,23 +1968,6 @@ main(int argc, char *argv[])
       case 'R':        /* Read file filter */
         rfilter = optarg;
         break;
-      case 's':        /* Set the snapshot (capture) length */
-#ifdef HAVE_LIBPCAP
-        capture_opts.has_snaplen = TRUE;
-        capture_opts.snaplen = get_positive_int(optarg, "snapshot length");
-#else
-        capture_option_specified = TRUE;
-        arg_error = TRUE;
-#endif
-        break;
-      case 'S':        /* "Sync" mode: used for following file ala tail -f */
-#ifdef HAVE_LIBPCAP
-        capture_opts.sync_mode = TRUE;
-#else
-        capture_option_specified = TRUE;
-        arg_error = TRUE;
-#endif
-        break;
       case 't':        /* Time stamp type */
         if (strcmp(optarg, "r") == 0)
           set_timestamp_setting(TS_RELATIVE);
@@ -2294,46 +1990,11 @@ main(int argc, char *argv[])
         break;
       case 'v':        /* Show version and exit */
         show_version();
-#ifdef WIN32
-        if (console_was_created)
-          destroy_console();
+#ifdef _WIN32
+        destroy_console();
 #endif
         exit(0);
         break;
-      case 'w':        /* Write to capture file xxx */
-#ifdef HAVE_LIBPCAP
-        save_file = g_strdup(optarg);
-#else
-        capture_option_specified = TRUE;
-        arg_error = TRUE;
-#endif
-       break;
-      case 'y':        /* Set the pcap data link type */
-#ifdef HAVE_LIBPCAP
-#ifdef HAVE_PCAP_DATALINK_NAME_TO_VAL
-        capture_opts.linktype = pcap_datalink_name_to_val(optarg);
-        if (capture_opts.linktype == -1) {
-          fprintf(stderr, "ethereal: The specified data link type \"%s\" is not valid\n",
-                  optarg);
-          exit(1);
-        }
-#else /* HAVE_PCAP_DATALINK_NAME_TO_VAL */
-        /* XXX - just treat it as a number */
-        capture_opts.linktype = get_natural_int(optarg, "data link type");
-#endif /* HAVE_PCAP_DATALINK_NAME_TO_VAL */
-#else /* HAVE_LIBPCAP */
-        capture_option_specified = TRUE;
-        arg_error = TRUE;
-#endif /* HAVE_LIBPCAP */
-        break;
-#ifdef HAVE_LIBPCAP
-      /* This is a hidden option supporting Sync mode, so we don't set
-       * the error flags for the user in the non-libpcap case.
-       */
-      case 'W':        /* Write to capture file FD xxx */
-        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))){
@@ -2350,21 +2011,6 @@ main(int argc, char *argv[])
           exit(1);
         }
         break;
-
-#ifdef _WIN32
-#ifdef HAVE_LIBPCAP
-      /* Hidden option supporting Sync mode */
-      case 'Z':        /* Write to pipe FD XXX */
-        /* associate stdout with pipe */
-        i = atoi(optarg);
-        if (dup2(i, 1) < 0) {
-          fprintf(stderr, "Unable to dup pipe handle\n");
-          exit(1);
-        }
-        break;
-#endif /* HAVE_LIBPCAP */
-#endif /* _WIN32 */
-
       default:
       case '?':        /* Bad flag - print usage message */
         arg_error = TRUE;
@@ -2397,6 +2043,8 @@ main(int argc, char *argv[])
     argv++;
   }
 
+
+
   if (argc != 0) {
     /*
      * Extra command line arguments were specified; complain.
@@ -2405,11 +2053,12 @@ main(int argc, char *argv[])
     arg_error = TRUE;
   }
 
+  if (arg_error) {
 #ifndef HAVE_LIBPCAP
-  if (capture_option_specified)
-    fprintf(stderr, "This version of Ethereal was not built with support for capturing packets.\n");
+    if (capture_option_specified) {
+      fprintf(stderr, "This version of Ethereal was not built with support for capturing packets.\n");
+    }
 #endif
-  if (arg_error) {
     print_usage(FALSE);
     exit(1);
   }
@@ -2417,7 +2066,7 @@ main(int argc, char *argv[])
 #ifdef HAVE_LIBPCAP
   if (start_capture && list_link_layer_types) {
     /* Specifying *both* is bogus. */
-    fprintf(stderr, "ethereal: You cannot specify both -L and a live capture.\n");
+    fprintf(stderr, "ethereal: You can't specify both -L and a live capture.\n");
     exit(1);
   }
 
@@ -2426,12 +2075,12 @@ main(int argc, char *argv[])
        did the user also specify a capture file to be read? */
     if (cf_name) {
       /* Yes - that's bogus. */
-      fprintf(stderr, "ethereal: You cannot specify -L and a capture file to be read.\n");
+      fprintf(stderr, "ethereal: You can't specify -L and a capture file to be read.\n");
       exit(1);
     }
     /* No - did they specify a ring buffer option? */
-    if (capture_opts.multi_files_on) {
-      fprintf(stderr, "ethereal: Ring buffer requested, but a capture is not being done.\n");
+    if (capture_opts->multi_files_on) {
+      fprintf(stderr, "ethereal: Ring buffer requested, but a capture isn't being done.\n");
       exit(1);
     }
   } else {
@@ -2439,41 +2088,41 @@ main(int argc, char *argv[])
        a capture file to be read? */
     if (start_capture && cf_name) {
       /* Yes - that's bogus. */
-      fprintf(stderr, "ethereal: You cannot specify both a live capture and a capture file to be read.\n");
+      fprintf(stderr, "ethereal: You can't specify both a live capture and a capture file to be read.\n");
       exit(1);
     }
 
     /* No - was the ring buffer option specified and, if so, does it make
        sense? */
-    if (capture_opts.multi_files_on) {
+    if (capture_opts->multi_files_on) {
       /* Ring buffer works only under certain conditions:
         a) ring buffer does not work with temporary files;
-        b) sync_mode and capture_opts.ringbuffer_on are mutually exclusive -
+        b) sync_mode and capture_opts->ringbuffer_on are mutually exclusive -
            sync_mode takes precedence;
         c) it makes no sense to enable the ring buffer if the maximum
            file size is set to "infinite". */
-      if (save_file == NULL) {
+      if (capture_opts->save_file == NULL) {
        fprintf(stderr, "ethereal: Ring buffer requested, but capture isn't being saved to a permanent file.\n");
-       capture_opts.multi_files_on = FALSE;
+       capture_opts->multi_files_on = FALSE;
       }
-      if (capture_opts.sync_mode) {
+      if (capture_opts->sync_mode) {
        fprintf(stderr, "ethereal: Ring buffer requested, but an \"Update list of packets in real time\" capture is being done.\n");
-       capture_opts.multi_files_on = FALSE;
+       capture_opts->multi_files_on = FALSE;
       }
-      if (!capture_opts.has_autostop_filesize) {
+      if (!capture_opts->has_autostop_filesize) {
        fprintf(stderr, "ethereal: Ring buffer requested, but no maximum capture file size was specified.\n");
-       capture_opts.multi_files_on = FALSE;
+       capture_opts->multi_files_on = FALSE;
       }
     }
   }
 
   if (start_capture || list_link_layer_types) {
     /* Did the user specify an interface to use? */
-    if (cfile.iface == NULL) {
+    if (capture_opts->iface == NULL) {
       /* No - is a default specified in the preferences file? */
       if (prefs->capture_device != NULL) {
           /* Yes - use it. */
-          cfile.iface = g_strdup(prefs->capture_device);
+          capture_opts->iface = g_strdup(prefs->capture_device);
       } else {
         /* No - pick the first one from the list of interfaces. */
         if_list = get_interface_list(&err, err_str);
@@ -2481,8 +2130,9 @@ main(int argc, char *argv[])
           switch (err) {
 
           case CANT_GET_INTERFACE_LIST:
-              fprintf(stderr, "ethereal: Can't get list of interfaces: %s\n",
-                       err_str);
+              cant_get_if_list_errstr = cant_get_if_list_error_message(err_str);
+              fprintf(stderr, "%s\n", cant_get_if_list_errstr);
+              g_free(cant_get_if_list_errstr);
               break;
 
           case NO_INTERFACES_FOUND:
@@ -2492,14 +2142,14 @@ main(int argc, char *argv[])
           exit(2);
         }
         if_info = if_list->data;       /* first interface */
-        cfile.iface = g_strdup(if_info->name);
+        capture_opts->iface = g_strdup(if_info->name);
         free_interface_list(if_list);
       }
     }
   }
 
-  if (capture_child) {
-    if (cfile.save_file_fd == -1) {
+  if (capture_opts->capture_child) {
+    if (capture_opts->save_file_fd == -1) {
       /* XXX - send this to the standard output as something our parent
         should put in an error message box? */
       fprintf(stderr, "%s: \"-W\" flag not specified\n", CHILD_NAME);
@@ -2509,7 +2159,7 @@ main(int argc, char *argv[])
 
   if (list_link_layer_types) {
     /* Get the list of link-layer types for the capture device. */
-    lt_list = get_pcap_linktype_list(cfile.iface, err_str);
+    lt_list = get_pcap_linktype_list(capture_opts->iface, err_str);
     if (lt_list == NULL) {
       if (err_str[0] != '\0') {
        fprintf(stderr, "ethereal: The list of data link types for the capture device could not be obtained (%s).\n"
@@ -2534,7 +2184,21 @@ main(int argc, char *argv[])
     exit(0);
   }
 
+  if (capture_opts->has_snaplen) {
+    if (capture_opts->snaplen < 1)
+      capture_opts->snaplen = WTAP_MAX_PACKET_SIZE;
+    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->ring_num_files > RINGBUFFER_MAX_NUM_FILES)
+    capture_opts->ring_num_files = RINGBUFFER_MAX_NUM_FILES;
+#if RINGBUFFER_MIN_NUM_FILES > 0
+  else if (capture_opts->num_files < RINGBUFFER_MIN_NUM_FILES)
+    capture_opts->ring_num_files = RINGBUFFER_MIN_NUM_FILES;
 #endif
+#endif /* HAVE_LIBPCAP */
 
   /* Notify all registered modules that have had any of their preferences
      changed either from one of the preferences file or from the command
@@ -2577,345 +2241,166 @@ main(int argc, char *argv[])
       }
   }
 
-#ifdef HAVE_LIBPCAP
-  if (capture_opts.has_snaplen) {
-    if (capture_opts.snaplen < 1)
-      capture_opts.snaplen = WTAP_MAX_PACKET_SIZE;
-    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.ring_num_files > RINGBUFFER_MAX_NUM_FILES)
-    capture_opts.ring_num_files = RINGBUFFER_MAX_NUM_FILES;
-#if RINGBUFFER_MIN_NUM_FILES > 0
-  else if (capture_opts.num_files < RINGBUFFER_MIN_NUM_FILES)
-    capture_opts.ring_num_files = RINGBUFFER_MIN_NUM_FILES;
-#endif
-#endif
-
-#ifdef WIN32
-#if GTK_MAJOR_VERSION >= 2
-  try_to_get_windows_font_gtk2();
-#endif
-#endif
-    
   /* read in rc file from global and personal configuration paths. */
+  /* XXX - is this a good idea? */
   gtk_rc_parse(RC_FILE);
   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 = font_boldify(prefs->gui_font_name1);
-  m_r_font = gdk_font_load(prefs->gui_font_name1);
-  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_name1);
-    } 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_name1);
-    prefs->gui_font_name1 = g_strdup("6x13");
-  }
-#else /* GTK_MAJOR_VERSION */
-  m_r_font = pango_font_description_from_string(prefs->gui_font_name2);
-  m_b_font = pango_font_description_copy(m_r_font);
-  pango_font_description_set_weight(m_b_font, PANGO_WEIGHT_BOLD);
-  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 Monospace 9\n",
-               prefs->gui_font_name2);
-    } else {
-      pango_font_description_free(m_r_font);
-    }
-    if (m_b_font == NULL) {
-#ifdef HAVE_LIBPCAP
-      if (!capture_child)
+  font_init(capture_opts->capture_child);
+#else
+  font_init(FALSE);
 #endif
-        fprintf(stderr, "ethereal: Warning: bold font %s not found - defaulting"
-                        " to Monospace 9\n", prefs->gui_font_name2);
-    } else {
-      pango_font_description_free(m_b_font);
-    }
-    if ((m_r_font = pango_font_description_from_string("Monospace 9")) == NULL)
-    {
-      fprintf(stderr, "ethereal: Error: font Monospace 9 not found\n");
-      exit(1);
-    }
-    if ((m_b_font = pango_font_description_copy(m_r_font)) == NULL) {
-      fprintf(stderr, "ethereal: Error: font Monospace 9 bold not found\n");
-      exit(1);
-    }
-    g_free(prefs->gui_font_name2);
-    pango_font_description_set_weight(m_b_font, PANGO_WEIGHT_BOLD);
-    prefs->gui_font_name2 = g_strdup("Monospace 9");
-  }
-#endif /* GTK_MAJOR_VERSION */
 
-  /* Call this for the side-effects that set_fonts() produces */
-  set_fonts(m_r_font, m_b_font);
+  /* close the splash screen, as we are going to open the main window now */
+  splash_destroy(splash_win);
+
 
 #ifdef HAVE_LIBPCAP
   /* Is this a "child" ethereal, which is only supposed to pop up a
      capture box to let us stop the capture, and run a capture
      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
-       we were told to. */
-    create_main_window(pl_size, tv_size, bv_size, prefs);
-
-    /* Read the recent file, as we have the gui now ready for it. */
-    read_recent(&rf_path, &rf_open_errno);
-
-    /* rearrange all the widgets */
-    main_widgets_rearrange();
-
-    /* Fill in column titles.  This must be done after the top level window
-       is displayed.
-
-       XXX - is that still true, with fixed-width columns? */
-    packet_list_set_column_titles();
-
-    menu_recent_read_finished();
-
-    switch (font_apply()) {
-    case FA_SUCCESS:
-        break;
-    case FA_FONT_NOT_RESIZEABLE:
-        /* "font_apply()" popped up an alert box. */
-        /* turn off zooming - font can't be resized */
-    case FA_FONT_NOT_AVAILABLE:
-        /* XXX - did we successfully load the un-zoomed version earlier?
-        If so, this *probably* means the font is available, but not at
-        this particular zoom level, but perhaps some other failure
-        occurred; I'm not sure you can determine which is the case,
-        however. */
-        /* turn off zooming - zoom level is unavailable */
-    default:
-        /* in any other case than FA_SUCCESS, turn off zooming */
-        recent.gui_zoom_level = 0;     
-        /* XXX: would it be a good idea to disable zooming (insensitive GUI)? */
-    }
-
-    dnd_init(top_level);
-
-    colors_init();
-    colfilter_init();
-
-    /* the window can be sized only, if it's not already shown, so do it now! */
-    main_load_window_geometry(top_level);
-
-    /*** we have finished all init things, show the main window ***/
-    gtk_widget_show(top_level);
-
-    /* the window can be maximized only, if it's visible, so do it after show! */
-    main_load_window_geometry(top_level);
-
-    /* process all pending GUI events before continue */
-    while (gtk_events_pending()) gtk_main_iteration();
-
-    /* If we were given the name of a capture file, read it in now;
-       we defer it until now, so that, if we can't open it, and pop
-       up an alert box, the alert box is more likely to come up on
-       top of the main window - but before the preference-file-error
-       alert box, so, if we get one of those, it's more likely to come
-       up on top of us. */
-    if (cf_name) {
-      if (rfilter != NULL) {
-        if (!dfilter_compile(rfilter, &rfcode)) {
-          bad_dfilter_alert_box(rfilter);
-          rfilter_parse_failed = TRUE;
-        }
-      }
-      if (!rfilter_parse_failed) {
-        if ((err = cf_open(cf_name, FALSE, &cfile)) == 0) {
-          /* "cf_open()" succeeded, so it closed the previous
-            capture file, and thus destroyed any previous read filter
-            attached to "cf". */
-          cfile.rfcode = rfcode;
-
-          /* Open tap windows; we do so after creating the main window,
-             to avoid GTK warnings, and after successfully opening the
-             capture file, so we know we have something to tap. */
-          if (tap_opt && tli) {
-            (*tli->func)(tap_opt);
-            g_free(tap_opt);
-          }
+  if (capture_opts->capture_child) {
+    /* This is the child process for a sync mode or fork mode capture,
+       so just do the low-level work of a capture - don't create
+       a temporary file and fork off *another* child process (so don't
+       call "do_capture()"). */
 
-          /* Read the capture file. */
-          switch (cf_read(&cfile)) {
+    /* Pop up any queued-up alert boxes. */
+    display_queued_messages();
 
-          case READ_SUCCESS:
-          case READ_ERROR:
-            /* Just because we got an error, that doesn't mean we were unable
-               to read any of the file; we handle what we could get from the
-               file. */
-            break;
+    /* XXX - hand these stats to the parent process */
+    capture_start(capture_opts, &stats_known, &stats);
 
-          case READ_ABORTED:
-            /* Exit now. */
-            gtk_exit(0);
-            break;
-          }
-          /* Save the name of the containing directory specified in the
-            path name, if any; we can write over cf_name, which is a
-             good thing, given that "get_dirname()" does write over its
-             argument. */
-          s = get_dirname(cf_name);
-          /* we might already set this from the recent file, don't overwrite this */
-          if(last_open_dir == NULL) 
-            set_last_open_dir(s);
-          g_free(cf_name);
-          cf_name = NULL;
-        } else {
-          if (rfcode != NULL)
-            dfilter_free(rfcode);
-          cfile.rfcode = NULL;
-        }
-      }
-    }
-#ifdef HAVE_LIBPCAP
+    /* The capture is done; there's nothing more for us to do. */
+    gtk_exit(0);
   }
 #endif
 
-  /* If the global preferences file exists but we failed to open it
-     or had an error reading 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) {
-    if (gpf_open_errno != 0) {
-      simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
-        "Could not open global preferences file\n\"%s\": %s.", gpf_path,
-        strerror(gpf_open_errno));
-    }
-    if (gpf_read_errno != 0) {
-      simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
-        "I/O error reading global preferences file\n\"%s\": %s.", gpf_path,
-        strerror(gpf_read_errno));
-    }
+  /***********************************************************************/
+  /* Everything is prepared now, preferences and command line was read in,
+       we are NOT a child window for a synced capture. */
+
+  /* Pop up the main window, and read in a capture file if
+     we were told to. */
+  create_main_window(pl_size, tv_size, bv_size, prefs);
+
+  /* Read the recent file, as we have the gui now ready for it. */
+  read_recent(&rf_path, &rf_open_errno);
+
+  /* rearrange all the widgets as we now have the recent settings for this */
+  main_widgets_rearrange();
+
+  /* Fill in column titles.  This must be done after the top level window
+     is displayed.
+
+     XXX - is that still true, with fixed-width columns? */
+  packet_list_set_column_titles();
+
+  menu_recent_read_finished();
+
+  switch (user_font_apply()) {
+  case FA_SUCCESS:
+      break;
+  case FA_FONT_NOT_RESIZEABLE:
+      /* "user_font_apply()" popped up an alert box. */
+      /* turn off zooming - font can't be resized */
+  case FA_FONT_NOT_AVAILABLE:
+      /* XXX - did we successfully load the un-zoomed version earlier?
+      If so, this *probably* means the font is available, but not at
+      this particular zoom level, but perhaps some other failure
+      occurred; I'm not sure you can determine which is the case,
+      however. */
+      /* turn off zooming - zoom level is unavailable */
+  default:
+      /* in any other case than FA_SUCCESS, turn off zooming */
+      recent.gui_zoom_level = 0;       
+      /* XXX: would it be a good idea to disable zooming (insensitive GUI)? */
   }
 
-  /* If the user's preferences file exists but we failed to open it
-     or had an error reading 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) {
-    if (pf_open_errno != 0) {
-      simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
-        "Could not open your preferences file\n\"%s\": %s.", pf_path,
-        strerror(pf_open_errno));
-    }
-    if (pf_read_errno != 0) {
-      simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
-        "I/O error reading your preferences file\n\"%s\": %s.", pf_path,
-        strerror(pf_read_errno));
+  dnd_init(top_level);
+
+  colors_init();
+  colfilter_init();
+  decode_as_init();
+
+  /* the window can be sized only, if it's not already shown, so do it now! */
+  main_load_window_geometry(top_level);
+
+  /* If we were given the name of a capture file, read it in now;
+     we defer it until now, so that, if we can't open it, and pop
+     up an alert box, the alert box is more likely to come up on
+     top of the main window - but before the preference-file-error
+     alert box, so, if we get one of those, it's more likely to come
+     up on top of us. */
+  if (cf_name) {
+    show_main_window(TRUE);
+    if (rfilter != NULL) {
+      if (!dfilter_compile(rfilter, &rfcode)) {
+        bad_dfilter_alert_box(rfilter);
+        rfilter_parse_failed = TRUE;
+      }
     }
-    g_free(pf_path);
-    pf_path = NULL;
-  }
+    if (!rfilter_parse_failed) {
+      if (cf_open(&cfile, cf_name, FALSE, &err) == CF_OK) {
+        /* "cf_open()" succeeded, so it closed the previous
+           capture file, and thus destroyed any previous read filter
+           attached to "cf". */
 
-  /* 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, ESD_BTN_OK,
-        "Could not open your capture filter file\n\"%s\": %s.", cf_path,
-        strerror(cf_open_errno));
-      g_free(cf_path);
-  }
+        cfile.rfcode = rfcode;
+        /* Open tap windows; we do so after creating the main window,
+           to avoid GTK warnings, and after successfully opening the
+           capture file, so we know we have something to tap. */
+        if (tap_opt && tli) {
+          (*tli->func)(tap_opt);
+          g_free(tap_opt);
+        }
 
-  /* 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, ESD_BTN_OK,
-        "Could not open your display filter file\n\"%s\": %s.", df_path,
-        strerror(df_open_errno));
-      g_free(df_path);
-  }
+        /* Read the capture file. */
+        switch (cf_read(&cfile)) {
 
-  /* If the global disabled protocols file exists but we failed to open it,
-     or had an error reading 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 (gdp_path != NULL) {
-    if (gdp_open_errno != 0) {
-      simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
-        "Could not open global disabled protocols file\n\"%s\": %s.",
-       gdp_path, strerror(gdp_open_errno));
-    }
-    if (gdp_read_errno != 0) {
-      simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
-        "I/O error reading global disabled protocols file\n\"%s\": %s.",
-       gdp_path, strerror(gdp_read_errno));
-    }
-    g_free(gdp_path);
-  }
+        case CF_READ_OK:
+        case CF_READ_ERROR:
+          /* Just because we got an error, that doesn't mean we were unable
+             to read any of the file; we handle what we could get from the
+             file. */
+          break;
 
-  /* If the user's disabled protocols file exists but we failed to open it,
-     or had an error reading 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 (dp_path != NULL) {
-    if (dp_open_errno != 0) {
-      simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
-        "Could not open your disabled protocols file\n\"%s\": %s.", dp_path,
-        strerror(dp_open_errno));
-    }
-    if (dp_read_errno != 0) {
-      simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
-        "I/O error reading your disabled protocols file\n\"%s\": %s.", dp_path,
-        strerror(dp_read_errno));
+        case CF_READ_ABORTED:
+          /* Exit now. */
+          gtk_exit(0);
+          break;
+        }
+        /* Save the name of the containing directory specified in the
+           path name, if any; we can write over cf_name, which is a
+           good thing, given that "get_dirname()" does write over its
+           argument. */
+        s = get_dirname(cf_name);
+        /* we might already set this from the recent file, don't overwrite this */
+        if(get_last_open_dir() == NULL) 
+          set_last_open_dir(s);
+        g_free(cf_name);
+        cf_name = NULL;
+      } else {
+        if (rfcode != NULL)
+          dfilter_free(rfcode);
+        cfile.rfcode = NULL;
+      }
     }
-    g_free(dp_path);
-  }
-
-#ifdef HAVE_LIBPCAP
-  if (capture_child) {
-    /* This is the child process for a sync mode or fork mode capture,
-       so just do the low-level work of a capture - don't create
-       a temporary file and fork off *another* child process (so don't
-       call "do_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);
   } else {
+#ifdef HAVE_LIBPCAP
     if (start_capture) {
+      if (capture_opts->save_file != NULL) {
+        /* Save the directory name for future file dialogs. */
+        /* (get_dirname overwrites filename) */
+        s = get_dirname(g_strdup(capture_opts->save_file));  
+        set_last_open_dir(s);
+        g_free(s);
+      }
       /* "-k" was specified; start a capture. */
-      if (do_capture(save_file)) {
+      show_main_window(TRUE);
+      if (do_capture(capture_opts)) {
         /* The capture started.  Open tap windows; we do so after creating
            the main window, to avoid GTK warnings, and after starting the
            capture, so we know we have something to tap. */
@@ -2924,588 +2409,133 @@ main(int argc, char *argv[])
           g_free(tap_opt);
         }
       }
-      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 {
+      show_main_window(FALSE);
       set_menus_for_capture_in_progress(FALSE);
     }
-  }
-
-  if (!start_capture && (cfile.cfilter == NULL || strlen(cfile.cfilter) == 0)) {
-    if (cfile.cfilter) {
-      g_free(cfile.cfilter);
-    }
-    cfile.cfilter = g_strdup(get_conn_cfilter());
-  }
-#else
-  set_menus_for_capture_in_progress(FALSE);
-#endif
-
-  gtk_main();
-
-  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
-     that "main()" returns without returning a value - it knows that
-     "exit()" never returns, but it doesn't know that "gtk_exit()"
-     doesn't, as GTK+ doesn't declare it with the attribute
-     "noreturn". */
-  return 0;    /* not reached */
-}
-
-#ifdef WIN32
-
-/* We build this as a GUI subsystem application on Win32, so
-   "WinMain()", not "main()", gets called.
-
-   Hack shamelessly stolen from the Win32 port of the GIMP. */
-#ifdef __GNUC__
-#define _stdcall  __attribute__((stdcall))
-#endif
-
-int _stdcall
-WinMain (struct HINSTANCE__ *hInstance,
-        struct HINSTANCE__ *hPrevInstance,
-        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
-
-#if GTK_MAJOR_VERSION < 2
-/* 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 *
-font_boldify(const char *font_name)
-{
-       char *bold_font_name;
-       gchar **xlfd_tokens;
-       unsigned 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);
-
-               /*
-                * Make sure we *have* a weight (this might not be a valid
-                * XLFD font name).
-                */
-               for (i = 0; i < XLFD_WEIGHT+1; i++) {
-                       if (xlfd_tokens[i] == NULL) {
-                               /*
-                                * We don't, so treat this as a non-XLFD
-                                * font name.
-                                */
-                               goto not_xlfd;
-                       }
-               }
-               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);
-               return bold_font_name;
-       }
-
-not_xlfd:
-       /*
-        * This isn't an XLFD font name; just append "bold" to the name
-        * of the font.
-        */
-       bold_font_name = g_strconcat(font_name, "bold", NULL);
-       return bold_font_name;
-}
-#endif
-
-/* Given a font name, construct the name of a version of that font with
-   the current zoom factor applied. */
-static char *
-font_zoom(char *gui_font_name)
-{
-    char *new_font_name;
-    char *font_name_dup;
-    char *font_name_p;
-    long font_point_size_l;
-#if GTK_MAJOR_VERSION < 2
-    int minus_chars;
-    char *font_foundry;
-    char *font_family;
-    char *font_weight;
-    char *font_slant;
-    char *font_set_width;
-    char *font_add_style;
-    char *font_pixel_size;
-    char *font_point_size;
-    char *font_res_x;
-    char *font_res_y;
-    char *font_spacing;
-    char *font_aver_width;
-    char *font_charset_reg;
-    char *font_charset_encoding;
-#endif
-
-    if (recent.gui_zoom_level == 0) {
-        /* There is no zoom factor - just return the name, so that if
-           this is GTK+ 1.2[.x] and the font name isn't an XLFD font
-           name, we don't fail. */
-        return g_strdup(gui_font_name);
-    }
-
-    font_name_dup = g_strdup(gui_font_name);
-    font_name_p = font_name_dup;
-
-#if GTK_MAJOR_VERSION >= 2
-    /* find the start of the font_size string */
-    font_name_p = strrchr(font_name_dup, ' ');
-    *font_name_p = '\0';
-    font_name_p++;
-
-    /* calculate the new font size */
-    font_point_size_l = strtol(font_name_p, NULL, 10);
-    font_point_size_l += recent.gui_zoom_level;
-
-    /* build a new font name */
-    new_font_name = g_strdup_printf("%s %ld", font_name_dup, font_point_size_l);
-#else
-    minus_chars = 0;
-    /* replace all '-' chars by NUL and count them */
-    while ((font_name_p = strchr(font_name_p, '-')) != NULL) {
-        *font_name_p = '\0';
-        font_name_p++;
-        minus_chars++;
-    }
-
-    if (minus_chars != 14) {
-        /*
-         * Not a valid XLFD font name.
-         * XXX - can we try scaling it by looking for a size at the end
-         * and tweaking that?  Unfortunately, some fonts have numbers
-         * at the end that aren't, as far as I know, sizes, e.g. "nil2".
-         */
-        return NULL;
-    }
-
-    /* first element (font name registry) empty */
-    font_name_p = font_name_dup;
-    font_name_p += strlen(font_name_p);
-    font_name_p++;
-
-    /* get pointers to all font name elements */
-    font_foundry = font_name_p;
-    font_name_p += strlen(font_name_p);
-    font_name_p++;
-
-    font_family = font_name_p;
-    font_name_p += strlen(font_name_p);
-    font_name_p++;
-
-    font_weight = font_name_p;
-    font_name_p += strlen(font_name_p);
-    font_name_p++;
-
-    font_slant = font_name_p;
-    font_name_p += strlen(font_name_p);
-    font_name_p++;
-
-    font_set_width = font_name_p;
-    font_name_p += strlen(font_name_p);
-    font_name_p++;
-
-    font_add_style = font_name_p;
-    font_name_p += strlen(font_name_p);
-    font_name_p++;
-
-    font_pixel_size = font_name_p;
-    font_name_p += strlen(font_name_p);
-    font_name_p++;
-
-    font_point_size = font_name_p;
-    font_name_p += strlen(font_name_p);
-    font_name_p++;
-
-    font_res_x = font_name_p;
-    font_name_p += strlen(font_name_p);
-    font_name_p++;
-
-    font_res_y = font_name_p;
-    font_name_p += strlen(font_name_p);
-    font_name_p++;
-
-    font_spacing = font_name_p;
-    font_name_p += strlen(font_name_p);
-    font_name_p++;
-
-    font_aver_width = font_name_p;
-    font_name_p += strlen(font_name_p);
-    font_name_p++;
-
-    font_charset_reg = font_name_p;
-    font_name_p += strlen(font_name_p);
-    font_name_p++;
-
-    font_charset_encoding = font_name_p;
-    font_name_p += strlen(font_name_p);
-    font_name_p++;
-
-    /* calculate the new font size */
-    font_point_size_l = strtol(font_point_size, NULL, 10);
-    font_point_size_l += recent.gui_zoom_level*10;
-    if (font_point_size_l <= 0)
-        font_point_size_l = 10;
-
-    /* build a new font name */
-    new_font_name = g_strdup_printf("-%s-%s-%s-%s-%s-%s-%s-%ld-%s-%s-%s-%s-%s-%s", 
-        font_foundry, font_family, font_weight, font_slant, font_set_width, 
-        font_add_style, font_pixel_size, font_point_size_l, font_res_x,
-        font_res_y, font_spacing, font_aver_width, font_charset_reg,
-        font_charset_encoding);
-#endif
-
-    g_free(font_name_dup);
-
-    return new_font_name;
-}
-
-fa_ret_t
-font_apply(void) {
-    char *gui_font_name;
-#if GTK_MAJOR_VERSION < 2
-    GdkFont *new_r_font, *new_b_font;
-    char *bold_font_name;
-    GdkFont *old_r_font = NULL, *old_b_font = NULL;
-#else
-    PangoFontDescription *new_r_font, *new_b_font;
-    PangoFontDescription *old_r_font = NULL, *old_b_font = NULL;
-#endif
-
-    /* convert font name to reflect the zoom level */
-    gui_font_name = font_zoom(prefs.PREFS_GUI_FONT_NAME);
-    if (gui_font_name == NULL) {
-       /*
-        * This means the font name isn't an XLFD font name.
-        * We just report that for now as a font not available in
-        * multiple sizes.
-        */
-        simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
-            "Your current font isn't available in any other sizes.\n");
-        return FA_FONT_NOT_RESIZEABLE;
-    }
-
-#if GTK_MAJOR_VERSION < 2
-    new_r_font = gdk_font_load(gui_font_name);
-    bold_font_name = font_boldify(gui_font_name);
-    new_b_font = gdk_font_load(bold_font_name);
-#else
-    new_r_font = pango_font_description_from_string(gui_font_name);
-    new_b_font = pango_font_description_copy(new_r_font);
-    pango_font_description_set_weight(new_b_font, PANGO_WEIGHT_BOLD);
-#endif
-    if (new_r_font == NULL || new_b_font == NULL) {
-        /* We're no longer using the new fonts; unreference them. */
-#if GTK_MAJOR_VERSION < 2
-        if (new_r_font != NULL)
-            gdk_font_unref(new_r_font);
-        if (new_b_font != NULL)
-            gdk_font_unref(new_b_font);
-#else
-        if (new_r_font != NULL)
-            pango_font_description_free(new_r_font);
-        if (new_b_font != NULL)
-            pango_font_description_free(new_b_font);
-#endif
-        g_free(gui_font_name);
-
-        /* We let our caller pop up a dialog box, as the error message
-           depends on the context (did they zoom in or out, or did they
-           do something else? */
-        return FA_FONT_NOT_AVAILABLE;
-    }
-
-    /* the font(s) seem to be ok */
-    set_plist_font(new_r_font);
-    set_ptree_font_all(new_r_font);
-    old_r_font = m_r_font;
-    old_b_font = m_b_font;
-    set_fonts(new_r_font, new_b_font);
-#if GTK_MAJOR_VERSION < 2
-    g_free(bold_font_name);
-#endif
-
-    /* Redraw the hex dump windows. */
-    redraw_hex_dump_all();
-
-    /* Redraw the "Follow TCP Stream" windows. */
-    follow_redraw_all();
-
-    /* We're no longer using the old fonts; unreference them. */
-#if GTK_MAJOR_VERSION < 2
-    if (old_r_font != NULL)
-        gdk_font_unref(old_r_font);
-    if (old_b_font != NULL)
-        gdk_font_unref(old_b_font);
-#else
-    if (old_r_font != NULL)
-        pango_font_description_free(old_r_font);
-    if (old_b_font != NULL)
-        pango_font_description_free(old_b_font);
-#endif
-    g_free(gui_font_name);
-    return FA_SUCCESS;
-}
-
-
-#ifdef WIN32
-
-#define NAME_BUFFER_LEN 32
-
-#if GTK_MAJOR_VERSION < 2
-
-
-/* The setting of the MS default font for system stuff (menus, dialogs, ...),
- * coming from: Allin Cottrell, http://www.ecn.wfu.edu/~cottrell/gtk_win32,
- * Thank you very much for this! */
-int get_windows_font_gtk1(char *fontspec, int fontspec_len)
-{
-    HDC h_dc;
-    HGDIOBJ h_font;
-    TEXTMETRIC tm;
-    char name[NAME_BUFFER_LEN];
-    int len, pix_height;
-
-    h_dc = CreateDC("DISPLAY", NULL, NULL, NULL);
-    if (h_dc == NULL) return 1;
-    h_font = GetStockObject(DEFAULT_GUI_FONT);
-    if (h_font == NULL || !SelectObject(h_dc, h_font)) {
-        DeleteDC(h_dc);
-        return 1;
-    }
-    len = GetTextFace(h_dc, NAME_BUFFER_LEN, name);
-    if (len <= 0) {
-        DeleteDC(h_dc);
-        return 1;
-    }
-    if (!GetTextMetrics(h_dc, &tm)) {
-        DeleteDC(h_dc);
-        return 1;
-    }
-    pix_height = tm.tmHeight;
-    DeleteDC(h_dc);
-    g_snprintf(fontspec, fontspec_len, "-*-%s-*-*-*-*-%i-*-*-*-p-*-iso8859-1", name,
-            pix_height);
-    return 0;
-}
 
-void set_app_font_gtk1(GtkWidget *top_level_w)
-{
-    GtkStyle *style;
-    char winfont[80];
-    style = gtk_widget_get_style(top_level);
-    if (get_windows_font_gtk1(winfont, sizeof(winfont)) == 0)
-        style->font = gdk_font_load(winfont);
-    if (style->font) gtk_widget_set_style(top_level, style);
-}
+    /* if the user didn't supplied a capture filter, use the one to filter out remote connections like SSH */
+    if (!start_capture && (capture_opts->cfilter == NULL || strlen(capture_opts->cfilter) == 0)) {
+      if (capture_opts->cfilter) {
+        g_free(capture_opts->cfilter);
+      }
+      capture_opts->cfilter = g_strdup(get_conn_cfilter());
+    }
+#else /* HAVE_LIBPCAP */
+    show_main_window(FALSE);
+    set_menus_for_capture_in_progress(FALSE);
+#endif /* HAVE_LIBPCAP */
+  }
 
-#else /* GTK_MAJOR_VERSION */
-static char appfontname[128] = "tahoma 8";
+  gtk_main();
 
-void set_app_font_gtk2(const char *fontname)
-{
-    GtkSettings *settings;
+  epan_cleanup();
+  g_free(rc_file);
 
-    if (fontname != NULL && *fontname == 0) return;
+#ifdef _WIN32
+  /* Shutdown windows sockets */
+  WSACleanup();
 
-    settings = gtk_settings_get_default();
+  /* 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. */
+  destroy_console();
+#endif
 
-    if (fontname == NULL) {
-       g_object_set(G_OBJECT(settings), "gtk-font-name", appfontname, NULL);
-    } else {
-       GtkWidget *w;
-       PangoFontDescription *pfd;
-       PangoContext *pc;
-       PangoFont *pfont;
-
-       w = gtk_label_new(NULL);
-       pfd = pango_font_description_from_string(fontname);
-       pc = gtk_widget_get_pango_context(w);
-       pfont = pango_context_load_font(pc, pfd);
-
-       if (pfont != NULL) {
-           strcpy(appfontname, fontname);
-           g_object_set(G_OBJECT(settings), "gtk-font-name", appfontname, NULL);
-       }
+  gtk_exit(0);
 
-       gtk_widget_destroy(w);
-       pango_font_description_free(pfd);
-    }
+  /* This isn't reached, but we need it to keep GCC from complaining
+     that "main()" returns without returning a value - it knows that
+     "exit()" never returns, but it doesn't know that "gtk_exit()"
+     doesn't, as GTK+ doesn't declare it with the attribute
+     "noreturn". */
+  return 0;    /* not reached */
 }
 
-char *default_windows_menu_fontspec_gtk2(void)
-{
-    gchar *fontspec = NULL;
-    NONCLIENTMETRICS ncm;
-
-    memset(&ncm, 0, sizeof ncm);
-    ncm.cbSize = sizeof ncm;
+#ifdef _WIN32
 
-    if (SystemParametersInfo(SPI_GETNONCLIENTMETRICS, ncm.cbSize, &ncm, 0)) {
-       HDC screen = GetDC(0);
-       double y_scale = 72.0 / GetDeviceCaps(screen, LOGPIXELSY);
-       int point_size = (int) (ncm.lfMenuFont.lfHeight * y_scale);
+/* We build this as a GUI subsystem application on Win32, so
+   "WinMain()", not "main()", gets called.
 
-       if (point_size < 0) point_size = -point_size;
-       fontspec = g_strdup_printf("%s %d", ncm.lfMenuFont.lfFaceName,
-                                  point_size);
-       ReleaseDC(0, screen);
-    }
+   Hack shamelessly stolen from the Win32 port of the GIMP. */
+#ifdef __GNUC__
+#define _stdcall  __attribute__((stdcall))
+#endif
 
-    return fontspec;
+int _stdcall
+WinMain (struct HINSTANCE__ *hInstance,
+        struct HINSTANCE__ *hPrevInstance,
+        char               *lpszCmdLine,
+        int                 nCmdShow)
+{
+  has_console = FALSE;
+  return main (__argc, __argv);
 }
 
-static void try_to_get_windows_font_gtk2(void)
+/*
+ * If this application has no console window to which its standard output
+ * would go, create one.
+ */
+void
+create_console(void)
 {
-    gchar *fontspec;
-
-    fontspec = default_windows_menu_fontspec_gtk2();
+  if (!has_console && prefs.gui_console_open != console_open_never) {
+    /* 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);
 
-    if (fontspec != NULL) {
-       int match = 0;
-       PangoFontDescription *pfd;
-       PangoFont *pfont;
-       PangoContext *pc;
-       GtkWidget *w;
+    /* Well, we have a console now. */
+    has_console = TRUE;
 
-       pfd = pango_font_description_from_string(fontspec);
+    /* 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);
+  }
+}
 
-       w = gtk_label_new(NULL);
-       pc = gtk_widget_get_pango_context(w);
-       pfont = pango_context_load_font(pc, pfd);
-       match = (pfont != NULL);
+static void
+destroy_console(void)
+{
+  if (has_console) {
+    printf("\n\nPress any key to exit\n");
+    _getch();
+    FreeConsole();
+  }
+}
 
-       pango_font_description_free(pfd);
-       g_object_unref(G_OBJECT(pc));
-       gtk_widget_destroy(w);
+/* 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.
 
-       if (match) set_app_font_gtk2(fontspec);
-       g_free(fontspec);
-    }
+   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 (has_console) {
+    /* 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 /* GTK_MAJOR_VERSION */
+#endif
 
-#endif /* WIN32 */
 
 GtkWidget *info_bar_new(void)
 {
@@ -3540,15 +2570,35 @@ void foreach_remove_a_child(GtkWidget *widget, gpointer data) {
     gtk_container_remove(GTK_CONTAINER(data), widget);
 }
 
+GtkWidget *main_widget_layout(gint layout_content)
+{
+    switch(layout_content) {
+    case(layout_pane_content_none):
+        return NULL;
+        break;
+    case(layout_pane_content_plist):
+        return pkt_scrollw;
+        break;
+    case(layout_pane_content_pdetails):
+        return tv_scrollw;
+        break;
+    case(layout_pane_content_pbytes):
+        return byte_nb_ptr;
+        break;
+    default:
+        g_assert_not_reached();
+        return NULL;
+    }
+}
+
+
 /*
  * Rearrange the main window widgets
  */
 void main_widgets_rearrange(void) {
-    gint widgets = 0;
-    GtkWidget *w[10];
-    /* XXX: add this to the recent settings */
-    gboolean filter_toolbar_show_in_statusbar = TRUE;
-
+    GtkWidget *first_pane_widget1, *first_pane_widget2;
+    GtkWidget *second_pane_widget1, *second_pane_widget2;
+    gboolean split_top_left;
 
     /* be a bit faster */
     gtk_widget_hide(main_vbox);
@@ -3560,84 +2610,358 @@ void main_widgets_rearrange(void) {
     gtk_widget_ref(pkt_scrollw);
     gtk_widget_ref(tv_scrollw);
     gtk_widget_ref(byte_nb_ptr);
-    gtk_widget_ref(upper_pane);
-    gtk_widget_ref(lower_pane);
     gtk_widget_ref(stat_hbox);
     gtk_widget_ref(info_bar);
     gtk_widget_ref(packets_bar);
+    gtk_widget_ref(status_pane);
+    gtk_widget_ref(main_pane_v1);
+    gtk_widget_ref(main_pane_v2);
+    gtk_widget_ref(main_pane_h1);
+    gtk_widget_ref(main_pane_h2);
+    gtk_widget_ref(welcome_pane);
 
     /* empty all containers participating */
     gtk_container_foreach(GTK_CONTAINER(main_vbox),     foreach_remove_a_child, main_vbox);
-    gtk_container_foreach(GTK_CONTAINER(upper_pane),    foreach_remove_a_child, upper_pane);
-    gtk_container_foreach(GTK_CONTAINER(lower_pane),    foreach_remove_a_child, lower_pane);
     gtk_container_foreach(GTK_CONTAINER(stat_hbox),     foreach_remove_a_child, stat_hbox);
+    gtk_container_foreach(GTK_CONTAINER(status_pane),   foreach_remove_a_child, status_pane);
+    gtk_container_foreach(GTK_CONTAINER(main_pane_v1),  foreach_remove_a_child, main_pane_v1);
+    gtk_container_foreach(GTK_CONTAINER(main_pane_v2),  foreach_remove_a_child, main_pane_v2);
+    gtk_container_foreach(GTK_CONTAINER(main_pane_h1),  foreach_remove_a_child, main_pane_h1);
+    gtk_container_foreach(GTK_CONTAINER(main_pane_h2),  foreach_remove_a_child, main_pane_h2);
 
     /* add the menubar always at the top */
     gtk_box_pack_start(GTK_BOX(main_vbox), menubar, FALSE, TRUE, 0);
 
     /* main toolbar */
-    if (recent.main_toolbar_show) {
-        gtk_box_pack_start(GTK_BOX(main_vbox), main_tb, FALSE, TRUE, 0);
-    }
+    gtk_box_pack_start(GTK_BOX(main_vbox), main_tb, FALSE, TRUE, 0);
 
     /* filter toolbar in toolbar area */
-    if (recent.filter_toolbar_show && !filter_toolbar_show_in_statusbar) {
+    if (!prefs.filter_toolbar_show_in_statusbar) {
         gtk_box_pack_start(GTK_BOX(main_vbox), filter_tb, FALSE, TRUE, 1);
     }
 
-    /* get the info, which and how many of the main widgets should be shown */
-    if (recent.packet_list_show) {
-        w[widgets++] = pkt_scrollw;
-    }
-
-    if (recent.tree_view_show) {
-        w[widgets++] = tv_scrollw;
-    }
-
-    if (recent.byte_view_show) {
-        w[widgets++] = byte_nb_ptr;
-    }
-
-    /* show the main widgets, depending on their number */
-    switch(widgets) {
-    case(0):
+    /* fill the main layout panes */
+    switch(prefs.gui_layout_type) {
+    case(layout_type_5):
+        main_first_pane  = main_pane_v1;
+        main_second_pane = main_pane_v2;
+        split_top_left = FALSE;
         break;
-    case(1):
-        gtk_container_add(GTK_CONTAINER(main_vbox), w[0]);
+    case(layout_type_2):
+        main_first_pane  = main_pane_v1;
+        main_second_pane = main_pane_h1;
+        split_top_left = FALSE;
         break;
-    case(2):
-        gtk_container_add(GTK_CONTAINER(main_vbox), upper_pane);
-        gtk_paned_pack1(GTK_PANED(upper_pane), w[0], TRUE, TRUE);
-        gtk_paned_pack2(GTK_PANED(upper_pane), w[1], FALSE, FALSE);
+    case(layout_type_1):
+        main_first_pane  = main_pane_v1;
+        main_second_pane = main_pane_h1;
+        split_top_left = TRUE;
         break;
-    case(3):
-        gtk_container_add(GTK_CONTAINER(main_vbox), upper_pane);
-        gtk_paned_add1(GTK_PANED(upper_pane), w[0]);
-        gtk_paned_add2(GTK_PANED(upper_pane), lower_pane);
-
-        gtk_paned_pack1(GTK_PANED(lower_pane), w[1], TRUE, TRUE);
-        gtk_paned_pack2(GTK_PANED(lower_pane), w[2], FALSE, FALSE);
+    case(layout_type_4):
+        main_first_pane  = main_pane_h1;
+        main_second_pane = main_pane_v1;
+        split_top_left = FALSE;
         break;
+    case(layout_type_3):
+        main_first_pane  = main_pane_h1;
+        main_second_pane = main_pane_v1;
+        split_top_left = TRUE;
+        break;
+    case(layout_type_6):
+        main_first_pane  = main_pane_h1;
+        main_second_pane = main_pane_h2;
+        split_top_left = FALSE;
+        break;
+    default:
+        main_first_pane = NULL;
+        main_second_pane = NULL;
+        split_top_left = FALSE;
+        g_assert_not_reached();
     }
+    if (split_top_left) {
+        first_pane_widget1 = main_second_pane;
+        second_pane_widget1 = main_widget_layout(prefs.gui_layout_content_1);
+        second_pane_widget2 = main_widget_layout(prefs.gui_layout_content_2);
+        first_pane_widget2 = main_widget_layout(prefs.gui_layout_content_3);
+    } else {
+        first_pane_widget1 = main_widget_layout(prefs.gui_layout_content_1);
+        first_pane_widget2 = main_second_pane;
+        second_pane_widget1 = main_widget_layout(prefs.gui_layout_content_2);
+        second_pane_widget2 = main_widget_layout(prefs.gui_layout_content_3);
+    }
+    if (first_pane_widget1 != NULL)
+        gtk_paned_add1(GTK_PANED(main_first_pane), first_pane_widget1);
+    if (first_pane_widget2 != NULL)
+        gtk_paned_add2(GTK_PANED(main_first_pane), first_pane_widget2);
+    if (second_pane_widget1 != NULL)
+        gtk_paned_pack1(GTK_PANED(main_second_pane), second_pane_widget1, TRUE, TRUE);
+    if (second_pane_widget2 != NULL)
+        gtk_paned_pack2(GTK_PANED(main_second_pane), second_pane_widget2, FALSE, FALSE);
+
+    gtk_container_add(GTK_CONTAINER(main_vbox), main_first_pane);
+
+    /* welcome pane */
+    gtk_box_pack_start(GTK_BOX(main_vbox), welcome_pane, TRUE, TRUE, 0);
 
     /* statusbar hbox */
-    if ((recent.filter_toolbar_show && filter_toolbar_show_in_statusbar) || recent.statusbar_show) {
-        gtk_box_pack_start(GTK_BOX(main_vbox), stat_hbox, FALSE, TRUE, 0);
-    }
+    gtk_box_pack_start(GTK_BOX(main_vbox), stat_hbox, FALSE, TRUE, 0);
 
     /* filter toolbar in statusbar hbox */
-    if (recent.filter_toolbar_show && filter_toolbar_show_in_statusbar) {
+    if (prefs.filter_toolbar_show_in_statusbar) {
         gtk_box_pack_start(GTK_BOX(stat_hbox), filter_tb, FALSE, TRUE, 1);
     }
 
     /* statusbar */
+    gtk_box_pack_start(GTK_BOX(stat_hbox), status_pane, TRUE, TRUE, 0);
+    gtk_paned_pack1(GTK_PANED(status_pane), info_bar, FALSE, FALSE);
+    gtk_paned_pack2(GTK_PANED(status_pane), packets_bar, FALSE, FALSE);
+
+    /* hide widgets on users recent settings */
+    main_widgets_show_or_hide();
+
+    gtk_widget_show(main_vbox);
+}
+
+static void
+is_widget_visible(GtkWidget *widget, gpointer data)
+{
+    gboolean *is_visible = data;
+
+    if (!*is_visible) {
+        if (GTK_WIDGET_VISIBLE(widget))
+            *is_visible = TRUE;
+    }
+}
+
+
+GtkWidget *
+welcome_item(gchar *stock_item, gchar * label, gchar * message, GtkSignalFunc callback, void *callback_data)
+{
+    GtkWidget *w, *item_hb;
+#if GTK_MAJOR_VERSION >= 2
+    gchar *formatted_message;
+#endif
+
+
+    item_hb = gtk_hbox_new(FALSE, 1);
+
+    w = BUTTON_NEW_FROM_STOCK(stock_item);
+    WIDGET_SET_SIZE(w, 60, 60);
+#if GTK_MAJOR_VERSION >= 2
+    gtk_button_set_label(GTK_BUTTON(w), label);
+#endif
+    gtk_box_pack_start(GTK_BOX(item_hb), w, FALSE, FALSE, 0);
+    SIGNAL_CONNECT(w, "clicked", callback, callback_data);
+
+    w = gtk_label_new(message);
+       gtk_misc_set_alignment (GTK_MISC(w), 0.0, 0.5);
+#if GTK_MAJOR_VERSION >= 2
+    formatted_message = g_strdup_printf("<span weight=\"bold\" size=\"x-large\">%s</span>", message);
+    gtk_label_set_markup(GTK_LABEL(w), formatted_message);
+    g_free(formatted_message);
+#endif
+
+    gtk_box_pack_start(GTK_BOX(item_hb), w, FALSE, FALSE, 10);
+
+    return item_hb;
+}
+
+
+/* XXX - the layout has to be improved */
+GtkWidget *
+welcome_new(void)
+{
+    GtkWidget *welcome_scrollw, *welcome_hb, *welcome_vb, *item_hb;
+    GtkWidget *w, *icon;
+    gchar * message;
+
+
+    welcome_scrollw = scrolled_window_new(NULL, NULL);
+
+    welcome_hb = gtk_hbox_new(FALSE, 1);
+       /*gtk_container_border_width(GTK_CONTAINER(welcome_hb), 20);*/
+
+    welcome_vb = gtk_vbox_new(FALSE, 1);
+
+    item_hb = gtk_hbox_new(FALSE, 1);
+
+    icon = xpm_to_widget_from_parent(top_level, eicon3d64_xpm);
+    gtk_box_pack_start(GTK_BOX(item_hb), icon, FALSE, FALSE, 5);
+
+#if GTK_MAJOR_VERSION < 2
+    message = "Welcome to Ethereal!";
+#else
+    message = "<span weight=\"bold\" size=\"25000\">" "Welcome to Ethereal!" "</span>";
+#endif
+    w = gtk_label_new(message);
+#if GTK_MAJOR_VERSION >= 2
+    gtk_label_set_markup(GTK_LABEL(w), message);
+#endif
+    gtk_misc_set_alignment (GTK_MISC(w), 0.0, 0.5);
+    gtk_box_pack_start(GTK_BOX(item_hb), w, TRUE, TRUE, 5);
+
+    gtk_box_pack_start(GTK_BOX(welcome_vb), item_hb, TRUE, FALSE, 5);
+
+    w = gtk_label_new("What would you like to do?");
+    gtk_box_pack_start(GTK_BOX(welcome_vb), w, FALSE, FALSE, 10);
+    gtk_misc_set_alignment (GTK_MISC(w), 0.0, 0.0);
+
+#ifdef HAVE_LIBPCAP
+    item_hb = welcome_item(ETHEREAL_STOCK_CAPTURE_START, 
+        "Capture",
+        "Capture live data from your network", 
+        GTK_SIGNAL_FUNC(capture_prep_cb), NULL);
+    gtk_box_pack_start(GTK_BOX(welcome_vb), item_hb, TRUE, FALSE, 5);
+#endif
+
+    item_hb = welcome_item(GTK_STOCK_OPEN, 
+        "Open",
+        "Open a previously captured file",
+        GTK_SIGNAL_FUNC(file_open_cmd_cb), NULL);
+    gtk_box_pack_start(GTK_BOX(welcome_vb), item_hb, TRUE, FALSE, 5);
+
+#if (GLIB_MAJOR_VERSION >= 2)
+    item_hb = welcome_item(GTK_STOCK_HOME, 
+        "Home",
+        "Visit the Ethereal homepage",
+        GTK_SIGNAL_FUNC(topic_cb), GINT_TO_POINTER(ONLINEPAGE_HOME));
+    gtk_box_pack_start(GTK_BOX(welcome_vb), item_hb, TRUE, FALSE, 5);
+#endif
+
+    /* the end */
+    w = gtk_label_new("");
+    gtk_box_pack_start(GTK_BOX(welcome_vb), w, TRUE, TRUE, 0);
+
+    w = gtk_label_new("");
+    gtk_box_pack_start(GTK_BOX(welcome_hb), w, TRUE, TRUE, 0);
+
+    gtk_box_pack_start(GTK_BOX(welcome_hb), welcome_vb, TRUE, TRUE, 0);
+
+    w = gtk_label_new("");
+    gtk_box_pack_start(GTK_BOX(welcome_hb), w, TRUE, TRUE, 0);
+
+    gtk_widget_show_all(welcome_hb);
+
+    gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(welcome_scrollw),
+                                          welcome_hb);
+    gtk_widget_show_all(welcome_scrollw);
+
+    return welcome_scrollw;
+}
+
+/*
+ * XXX - this doesn't appear to work with the paned widgets in
+ * GTK+ 1.2[.x]; if you hide one of the panes, the splitter remains
+ * and the other pane doesn't grow to take up the rest of the pane.
+ * It does appear to work with GTK+ 2.x.
+ */
+void
+main_widgets_show_or_hide(void)
+{
+    gboolean main_second_pane_show;
+
+    if (recent.main_toolbar_show) {
+        gtk_widget_show(main_tb);
+    } else {
+        gtk_widget_hide(main_tb);
+    }
+
+    /*
+     * Show the status hbox if either:
+     *
+     *    1) we're showing the filter toolbar and we want it in the status
+     *       line
+     *
+     * or
+     *
+     *    2) we're showing the status bar.
+     */
+    if ((recent.filter_toolbar_show && prefs.filter_toolbar_show_in_statusbar) ||
+         recent.statusbar_show) {
+        gtk_widget_show(stat_hbox);
+    } else {
+        gtk_widget_hide(stat_hbox);
+    }
+
     if (recent.statusbar_show) {
-        gtk_box_pack_start(GTK_BOX(stat_hbox), info_bar, TRUE, TRUE, 0);
-        gtk_box_pack_start(GTK_BOX(stat_hbox), packets_bar, TRUE, TRUE, 0);
+        gtk_widget_show(status_pane);
+    } else {
+        gtk_widget_hide(status_pane);
     }
 
-    gtk_widget_show(main_vbox);
+    if (recent.filter_toolbar_show) {
+        gtk_widget_show(filter_tb);
+    } else {
+        gtk_widget_hide(filter_tb);
+    }
+
+    if (recent.packet_list_show && have_capture_file) {
+        gtk_widget_show(pkt_scrollw);
+    } else {
+        gtk_widget_hide(pkt_scrollw);
+    }
+
+    if (recent.tree_view_show && have_capture_file) {
+        gtk_widget_show(tv_scrollw);
+    } else {
+        gtk_widget_hide(tv_scrollw);
+    }
+
+    if (recent.byte_view_show && have_capture_file) {
+        gtk_widget_show(byte_nb_ptr);
+    } else {
+        gtk_widget_hide(byte_nb_ptr);
+    }
+
+    if (have_capture_file) {
+        gtk_widget_show(main_first_pane);
+    } else {
+        gtk_widget_hide(main_first_pane);
+    }
+
+    /*
+     * Is anything in "main_second_pane" visible?
+     * If so, show it, otherwise hide it.
+     */
+    main_second_pane_show = FALSE;
+    gtk_container_foreach(GTK_CONTAINER(main_second_pane), is_widget_visible,
+                          &main_second_pane_show);
+    if (main_second_pane_show) {
+        gtk_widget_show(main_second_pane);
+    } else {
+        gtk_widget_hide(main_second_pane);
+    }
+
+    if (!have_capture_file) {
+        if(welcome_pane) {
+            gtk_widget_show(welcome_pane);
+        }
+    } else {
+        gtk_widget_hide(welcome_pane);
+    }
+}
+
+
+#if GTK_MAJOR_VERSION >= 2
+/* called, when the window state changes (minimized, maximized, ...) */
+static int
+window_state_event_cb (GtkWidget *widget _U_,
+                       GdkEvent *event,
+                       gpointer  data _U_)
+{
+    GdkWindowState new_window_state = ((GdkEventWindowState*)event)->new_window_state;
+
+    if( (event->type) == (GDK_WINDOW_STATE)) {
+        if(!(new_window_state & GDK_WINDOW_STATE_ICONIFIED)) {
+            /* we might have dialogs popped up while we where iconified,
+               show em now */
+            display_queued_messages();
+        }
+    }
+    return FALSE;
 }
+#endif
+
 
 static void
 create_main_window (gint pl_size, gint tv_size, gint bv_size, e_prefs *prefs)
@@ -3650,6 +2974,7 @@ create_main_window (gint pl_size, gint tv_size, gint bv_size, e_prefs *prefs)
     GList         *filter_list = NULL;
     GtkTooltips   *tooltips;
     GtkAccelGroup *accel;
+       gchar         *title;
     /* 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). */
@@ -3659,20 +2984,30 @@ create_main_window (gint pl_size, gint tv_size, gint bv_size, e_prefs *prefs)
         TRUE
     };
 
+    /* use user-defined title if preference is set */
+    title = create_user_window_title("The Ethereal Network Analyzer");
+
     /* Main window */
-    top_level = window_new(GTK_WINDOW_TOPLEVEL, "The Ethereal Network Analyzer");
+    top_level = window_new(GTK_WINDOW_TOPLEVEL, title);
+    g_free(title);
 
     tooltips = gtk_tooltips_new();
 
-#ifdef WIN32 
+#ifdef _WIN32 
 #if GTK_MAJOR_VERSION < 2
-    set_app_font_gtk1(top_level);
+    /* has to be done, after top_level window is created */
+    app_font_gtk1_init(top_level);
 #endif
 #endif
     
     gtk_widget_set_name(top_level, "main window");
     SIGNAL_CONNECT(top_level, "delete_event", main_window_delete_event_cb,
                    NULL);
+#if GTK_MAJOR_VERSION >= 2
+    SIGNAL_CONNECT(GTK_OBJECT(top_level), "window_state_event",
+                         G_CALLBACK (window_state_event_cb), NULL);
+#endif
+
     gtk_window_set_policy(GTK_WINDOW(top_level), TRUE, TRUE, FALSE);
 
     /* Container for menu bar, toolbar(s), paned windows and progress/info box */
@@ -3696,11 +3031,6 @@ create_main_window (gint pl_size, gint tv_size, gint bv_size, e_prefs *prefs)
     gtk_widget_show(pkt_scrollw);
 
     /* 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
     tv_scrollw = main_tree_view_new(prefs, &tree_view);
     WIDGET_SET_SIZE(tv_scrollw, -1, tv_size);
     gtk_widget_show(tv_scrollw);
@@ -3727,13 +3057,14 @@ create_main_window (gint pl_size, gint tv_size, gint bv_size, e_prefs *prefs)
 
 
     /* Panes for the packet list, tree, and byte view */
-    lower_pane = gtk_vpaned_new();
-    gtk_paned_gutter_size(GTK_PANED(lower_pane), (GTK_PANED(lower_pane))->handle_size);
-    gtk_widget_show(lower_pane);
-
-    upper_pane = gtk_vpaned_new();
-    gtk_paned_gutter_size(GTK_PANED(upper_pane), (GTK_PANED(upper_pane))->handle_size);
-    gtk_widget_show(upper_pane);
+    main_pane_v1 = gtk_vpaned_new();
+    gtk_widget_show(main_pane_v1);
+    main_pane_v2 = gtk_vpaned_new();
+    gtk_widget_show(main_pane_v2);
+    main_pane_h1 = gtk_hpaned_new();
+    gtk_widget_show(main_pane_h1);
+    main_pane_h2 = gtk_hpaned_new();
+    gtk_widget_show(main_pane_h2);
 
     /* filter toolbar */
 #if GTK_MAJOR_VERSION < 2
@@ -3746,6 +3077,7 @@ create_main_window (gint pl_size, gint tv_size, gint bv_size, e_prefs *prefs)
 #endif /* GTK_MAJOR_VERSION */
     gtk_widget_show(filter_tb);
 
+    /* Create the "Filter:" button */
     filter_bt = BUTTON_NEW_FROM_STOCK(ETHEREAL_STOCK_DISPLAY_FILTER_ENTRY);
     SIGNAL_CONNECT(filter_bt, "clicked", display_filter_construct_cb, &args);
     gtk_widget_show(filter_bt);
@@ -3754,6 +3086,7 @@ create_main_window (gint pl_size, gint tv_size, gint bv_size, e_prefs *prefs)
     gtk_toolbar_append_widget(GTK_TOOLBAR(filter_tb), filter_bt, 
         "Open the \"Display Filter\" dialog, to edit/apply filters", "Private");
 
+    /* Create the filter combobox */
     filter_cm = gtk_combo_new();
     filter_list = NULL;
     gtk_combo_disable_activate(GTK_COMBO(filter_cm));
@@ -3785,6 +3118,7 @@ create_main_window (gint pl_size, gint tv_size, gint bv_size, e_prefs *prefs)
     gtk_toolbar_append_widget(GTK_TOOLBAR(filter_tb), filter_add_expr_bt, 
         "Add an expression to this filter string", "Private");
 
+    /* Create the "Clear" button */
     filter_reset = BUTTON_NEW_FROM_STOCK(GTK_STOCK_CLEAR);
     OBJECT_SET_DATA(filter_reset, E_DFILTER_TE_KEY, filter_te);
     SIGNAL_CONNECT(filter_reset, "clicked", filter_reset_cb, NULL);
@@ -3792,6 +3126,7 @@ create_main_window (gint pl_size, gint tv_size, gint bv_size, e_prefs *prefs)
     gtk_toolbar_append_widget(GTK_TOOLBAR(filter_tb), filter_reset, 
         "Clear this filter string and update the display", "Private");
 
+    /* Create the "Apply" button */
     filter_apply = BUTTON_NEW_FROM_STOCK(GTK_STOCK_APPLY);
     OBJECT_SET_DATA(filter_apply, E_DFILTER_CM_KEY, filter_cm);
     SIGNAL_CONNECT(filter_apply, "clicked", filter_activate_cb, filter_te);
@@ -3807,29 +3142,29 @@ create_main_window (gint pl_size, gint tv_size, gint bv_size, e_prefs *prefs)
                          filter_te);
     set_menu_object_data("/Analyze/Follow TCP Stream", E_DFILTER_TE_KEY,
                          filter_te);
-    set_menu_object_data("/Analyze/Match/Selected", E_DFILTER_TE_KEY,
+    set_menu_object_data("/Analyze/Apply as Filter/Selected", E_DFILTER_TE_KEY,
                          filter_te);
-    set_menu_object_data("/Analyze/Match/Not Selected", E_DFILTER_TE_KEY,
+    set_menu_object_data("/Analyze/Apply as Filter/Not Selected", E_DFILTER_TE_KEY,
                          filter_te);
-    set_menu_object_data("/Analyze/Match/And Selected", E_DFILTER_TE_KEY,
+    set_menu_object_data("/Analyze/Apply as Filter/... and Selected", E_DFILTER_TE_KEY,
                          filter_te);
-    set_menu_object_data("/Analyze/Match/Or Selected", E_DFILTER_TE_KEY,
+    set_menu_object_data("/Analyze/Apply as Filter/... or Selected", E_DFILTER_TE_KEY,
                          filter_te);
-    set_menu_object_data("/Analyze/Match/And Not Selected", E_DFILTER_TE_KEY,
+    set_menu_object_data("/Analyze/Apply as Filter/... and not Selected", E_DFILTER_TE_KEY,
                          filter_te);
-    set_menu_object_data("/Analyze/Match/Or Not Selected", E_DFILTER_TE_KEY,
+    set_menu_object_data("/Analyze/Apply as Filter/... or not Selected", E_DFILTER_TE_KEY,
                          filter_te);
-    set_menu_object_data("/Analyze/Prepare/Selected", E_DFILTER_TE_KEY,
+    set_menu_object_data("/Analyze/Prepare a Filter/Selected", E_DFILTER_TE_KEY,
                          filter_te);
-    set_menu_object_data("/Analyze/Prepare/Not Selected", E_DFILTER_TE_KEY,
+    set_menu_object_data("/Analyze/Prepare a Filter/Not Selected", E_DFILTER_TE_KEY,
                          filter_te);
-    set_menu_object_data("/Analyze/Prepare/And Selected", E_DFILTER_TE_KEY,
+    set_menu_object_data("/Analyze/Prepare a Filter/... and Selected", E_DFILTER_TE_KEY,
                          filter_te);
-    set_menu_object_data("/Analyze/Prepare/Or Selected", E_DFILTER_TE_KEY,
+    set_menu_object_data("/Analyze/Prepare a Filter/... or Selected", E_DFILTER_TE_KEY,
                          filter_te);
-    set_menu_object_data("/Analyze/Prepare/And Not Selected", E_DFILTER_TE_KEY,
+    set_menu_object_data("/Analyze/Prepare a Filter/... and not Selected", E_DFILTER_TE_KEY,
                          filter_te);
-    set_menu_object_data("/Analyze/Prepare/Or Not Selected", E_DFILTER_TE_KEY,
+    set_menu_object_data("/Analyze/Prepare a Filter/... or not Selected", E_DFILTER_TE_KEY,
                          filter_te);
     set_toolbar_object_data(E_DFILTER_TE_KEY, filter_te);
     OBJECT_SET_DATA(popup_menu_object, E_DFILTER_TE_KEY, filter_te);
@@ -3847,37 +3182,30 @@ create_main_window (gint pl_size, gint tv_size, gint bv_size, e_prefs *prefs)
     stat_hbox = gtk_hbox_new(FALSE, 1);
     gtk_container_border_width(GTK_CONTAINER(stat_hbox), 0);
     gtk_widget_show(stat_hbox);
-}
 
+    /* Pane for the statusbar */
+    status_pane = gtk_hpaned_new();
+    gtk_widget_show(status_pane);
 
-void
-set_last_open_dir(char *dirname)
+    /* Pane for the welcome screen */
+    welcome_pane = welcome_new();
+    gtk_widget_show(welcome_pane);
+}
+
+static void
+show_main_window(gboolean doing_work)
 {
-       int len;
-       gchar *new_last_open_dir;
+  main_set_for_capture_file(doing_work);
 
-       if (dirname) {
-               len = strlen(dirname);
-               if (dirname[len-1] == G_DIR_SEPARATOR) {
-                       new_last_open_dir = g_strconcat(dirname, NULL);
-               }
-               else {
-                       new_last_open_dir = g_strconcat(dirname,
-                               G_DIR_SEPARATOR_S, NULL);
-               }
+  /*** we have finished all init things, show the main window ***/
+  gtk_widget_show(top_level);
 
-               if (last_open_dir == NULL ||
-                   strcmp(last_open_dir, new_last_open_dir) != 0)
-                       updated_last_open_dir = TRUE;
-       }
-       else {
-               new_last_open_dir = NULL;
-               if (last_open_dir != NULL)
-                       updated_last_open_dir = TRUE;
-       }
+  /* the window can be maximized only, if it's visible, so do it after show! */
+  main_load_window_geometry(top_level);
 
-       if (last_open_dir) {
-               g_free(last_open_dir);
-       }
-       last_open_dir = new_last_open_dir;
+  /* process all pending GUI events before continue */
+  while (gtk_events_pending()) gtk_main_iteration();
+
+  /* Pop up any queued-up alert boxes. */
+  display_queued_messages();
 }