Removed trailing whitespaces from .h and .c files using the
[obnox/wireshark/wip.git] / file.c
diff --git a/file.c b/file.c
index b73db738eb0d80883c4463b6f934a0feb81bf449..9b3db605baa6c17fc9374fb9c425e053d0aa2957 100644 (file)
--- a/file.c
+++ b/file.c
@@ -1,12 +1,11 @@
 /* file.c
  * File I/O routines
  *
 /* file.c
  * File I/O routines
  *
- * $Id: file.c,v 1.224 2000/10/06 10:10:46 gram Exp $
+ * $Id: file.c,v 1.286 2002/08/28 10:07:26 guy Exp $
  *
  * Ethereal - Network traffic analyzer
  *
  * Ethereal - Network traffic analyzer
- * By Gerald Combs <gerald@zing.org>
+ * By Gerald Combs <gerald@ethereal.com>
  * Copyright 1998 Gerald Combs
  * Copyright 1998 Gerald Combs
- *
  * 
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
  * 
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
 #include "strerror.h"
 #endif
 
 #include "strerror.h"
 #endif
 
-#ifdef HAVE_SYS_TYPES_H
-# include <sys/types.h>
-#endif
-
-#ifdef HAVE_NETINET_IN_H
-# include <netinet/in.h>
-#endif
-
-#include <epan.h>
+#include <epan/epan.h>
+#include <epan/filesystem.h>
 
 #include "gtk/main.h"
 
 #include "gtk/main.h"
+#include "color.h"
+#include "gtk/color_utils.h"
 #include "column.h"
 #include "column.h"
-#include "packet.h"
+#include <epan/packet.h>
 #include "print.h"
 #include "file.h"
 #include "menu.h"
 #include "util.h"
 #include "simple_dialog.h"
 #include "print.h"
 #include "file.h"
 #include "menu.h"
 #include "util.h"
 #include "simple_dialog.h"
+#include "progress_dlg.h"
 #include "ui_util.h"
 #include "ui_util.h"
+#include "statusbar.h"
 #include "prefs.h"
 #include "gtk/proto_draw.h"
 #include "prefs.h"
 #include "gtk/proto_draw.h"
-#include "dfilter.h"
-#include "conversation.h"
+#include "gtk/packet_win.h"
+#include <epan/dfilter/dfilter.h>
+#include <epan/conversation.h>
 #include "globals.h"
 #include "globals.h"
+#include "gtk/colors.h"
+#include <epan/epan_dissect.h>
 
 
-#include "plugins.h"
+extern GtkWidget *packet_list, *byte_nb_ptr, *tree_view;
 
 
-extern GtkWidget *packet_list, *info_bar, *byte_view, *tree_view;
-extern guint      file_ctx;
-
-gboolean auto_scroll_live = FALSE;
+#ifdef HAVE_LIBPCAP
+gboolean auto_scroll_live;
+#endif
 
 static guint32 firstsec, firstusec;
 static guint32 prevsec, prevusec;
 
 
 static guint32 firstsec, firstusec;
 static guint32 prevsec, prevusec;
 
-static void read_packet(capture_file *cf, int offset);
+static void read_packet(capture_file *cf, long offset);
 
 
-static void rescan_packets(capture_file *cf, const char *action,
+static void rescan_packets(capture_file *cf, const char *action, const char *action_item,
        gboolean refilter, gboolean redissect);
 
 static void set_selected_row(int row);
        gboolean refilter, gboolean redissect);
 
 static void set_selected_row(int row);
@@ -122,7 +120,6 @@ open_cap_file(char *fname, gboolean is_tempfile, capture_file *cf)
 {
   wtap       *wth;
   int         err;
 {
   wtap       *wth;
   int         err;
-  FILE_T      fh;
   int         fd;
   struct stat cf_stat;
 
   int         fd;
   struct stat cf_stat;
 
@@ -131,7 +128,6 @@ open_cap_file(char *fname, gboolean is_tempfile, capture_file *cf)
     goto fail;
 
   /* Find the size of the file. */
     goto fail;
 
   /* Find the size of the file. */
-  fh = wtap_file(wth);
   fd = wtap_fd(wth);
   if (fstat(fd, &cf_stat) < 0) {
     err = errno;
   fd = wtap_fd(wth);
   if (fstat(fd, &cf_stat) < 0) {
     err = errno;
@@ -141,13 +137,10 @@ open_cap_file(char *fname, gboolean is_tempfile, capture_file *cf)
 
   /* The open succeeded.  Close whatever capture file we had open,
      and fill in the information for this file. */
 
   /* The open succeeded.  Close whatever capture file we had open,
      and fill in the information for this file. */
-  close_cap_file(cf, info_bar);
-
-  /* Initialize the table of conversations. */
-  epan_conversation_init();
+  close_cap_file(cf);
 
 
-  /* Initialize protocol-specific variables */
-  init_all_protocols();
+  /* Initialize all data structures used for dissection. */
+  init_dissection();
 
   /* We're about to start reading the file. */
   cf->state = FILE_READ_IN_PROGRESS;
 
   /* We're about to start reading the file. */
   cf->state = FILE_READ_IN_PROGRESS;
@@ -169,10 +162,18 @@ open_cap_file(char *fname, gboolean is_tempfile, capture_file *cf)
 
   cf->cd_t      = wtap_file_type(cf->wth);
   cf->count     = 0;
 
   cf->cd_t      = wtap_file_type(cf->wth);
   cf->count     = 0;
+  cf->marked_count = 0;
+  cf->drops_known = FALSE;
   cf->drops     = 0;
   cf->esec      = 0;
   cf->eusec     = 0;
   cf->snap      = wtap_snapshot_length(cf->wth);
   cf->drops     = 0;
   cf->esec      = 0;
   cf->eusec     = 0;
   cf->snap      = wtap_snapshot_length(cf->wth);
+  if (cf->snap == 0) {
+    /* Snapshot length not known. */
+    cf->has_snap = FALSE;
+    cf->snap = WTAP_MAX_PACKET_SIZE;
+  } else
+    cf->has_snap = TRUE;
   cf->progbar_quantum = 0;
   cf->progbar_nextstep = 0;
   firstsec = 0, firstusec = 0;
   cf->progbar_quantum = 0;
   cf->progbar_nextstep = 0;
   firstsec = 0, firstusec = 0;
@@ -188,13 +189,13 @@ open_cap_file(char *fname, gboolean is_tempfile, capture_file *cf)
 
 fail:
   simple_dialog(ESD_TYPE_CRIT, NULL,
 
 fail:
   simple_dialog(ESD_TYPE_CRIT, NULL,
-                       file_open_error_message(err, FALSE), fname);
+                       file_open_error_message(err, FALSE, 0), fname);
   return (err);
 }
 
 /* Reset everything to a pristine state */
 void
   return (err);
 }
 
 /* Reset everything to a pristine state */
 void
-close_cap_file(capture_file *cf, void *w)
+close_cap_file(capture_file *cf)
 {
   /* Die if we're in the middle of reading a file. */
   g_assert(cf->state != FILE_READ_IN_PROGRESS);
 {
   /* Die if we're in the middle of reading a file. */
   g_assert(cf->state != FILE_READ_IN_PROGRESS);
@@ -223,7 +224,7 @@ close_cap_file(capture_file *cf, void *w)
     cf->plist_chunk = NULL;
   }
   if (cf->rfcode != NULL) {
     cf->plist_chunk = NULL;
   }
   if (cf->rfcode != NULL) {
-    dfilter_destroy(cf->rfcode);
+    dfilter_free(cf->rfcode);
     cf->rfcode = NULL;
   }
   cf->plist = NULL;
     cf->rfcode = NULL;
   }
   cf->plist = NULL;
@@ -240,7 +241,7 @@ close_cap_file(capture_file *cf, void *w)
   /* 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? */
   /* 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? */
-  gtk_statusbar_pop(GTK_STATUSBAR(w), file_ctx);
+  statusbar_pop_file_msg();
 
   /* Restore the standard title bar message. */
   set_main_window_name("The Ethereal Network Analyzer");
 
   /* Restore the standard title bar message. */
   set_main_window_name("The Ethereal Network Analyzer");
@@ -264,7 +265,8 @@ set_display_filename(capture_file *cf)
 {
   gchar  *name_ptr;
   size_t  msg_len;
 {
   gchar  *name_ptr;
   size_t  msg_len;
-  gchar  *done_fmt = " File: %s  Drops: %u";
+  static const gchar done_fmt_nodrops[] = " File: %s";
+  static const gchar done_fmt_drops[] = " File: %s  Drops: %u";
   gchar  *done_msg;
   gchar  *win_name_fmt = "%s - Ethereal";
   gchar  *win_name;
   gchar  *done_msg;
   gchar  *win_name_fmt = "%s - Ethereal";
   gchar  *win_name;
@@ -279,10 +281,16 @@ set_display_filename(capture_file *cf)
     name_ptr = "<capture>";
   }
 
     name_ptr = "<capture>";
   }
 
-  msg_len = strlen(name_ptr) + strlen(done_fmt) + 64;
-  done_msg = g_malloc(msg_len);
-  snprintf(done_msg, msg_len, done_fmt, name_ptr, cf->drops);
-  gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx, done_msg);
+  if (cf->drops_known) {
+    msg_len = strlen(name_ptr) + strlen(done_fmt_drops) + 64;
+    done_msg = g_malloc(msg_len);
+    snprintf(done_msg, msg_len, done_fmt_drops, name_ptr, cf->drops);
+  } else {
+    msg_len = strlen(name_ptr) + strlen(done_fmt_nodrops);
+    done_msg = g_malloc(msg_len);
+    snprintf(done_msg, msg_len, done_fmt_nodrops, name_ptr);
+  }
+  statusbar_push_file_msg(done_msg);
   g_free(done_msg);
 
   msg_len = strlen(name_ptr) + strlen(win_name_fmt) + 1;
   g_free(done_msg);
 
   msg_len = strlen(name_ptr) + strlen(win_name_fmt) + 1;
@@ -295,23 +303,32 @@ set_display_filename(capture_file *cf)
 read_status_t
 read_cap_file(capture_file *cf, int *err)
 {
 read_status_t
 read_cap_file(capture_file *cf, int *err)
 {
-  gchar    *name_ptr, *load_msg, *load_fmt = " Loading: %s...";
-  size_t    msg_len;
-  char     *errmsg;
-  char      errmsg_errno[1024+1];
-  gchar     err_str[2048+1];
-  int       data_offset;
-  progdlg_t *progbar;
-  gboolean  stop_flag;
-  int       file_pos;
-  float     prog_val;
+  gchar      *name_ptr, *load_msg, *load_fmt = "%s";
+  size_t      msg_len;
+  char       *errmsg;
+  char        errmsg_errno[1024+1];
+  gchar       err_str[2048+1];
+  long        data_offset;
+  progdlg_t  *progbar = NULL;
+  gboolean    stop_flag;
+  /*
+   * XXX - should be "off_t", but Wiretap would need more work to handle
+   * the full size of "off_t" on platforms where it's more than a "long"
+   * as well.
+   */
+  long        file_pos;
+  float       prog_val;
+  int         fd;
+  struct stat cf_stat;
+  GTimeVal    start_time;
+  gchar       status_str[100];
 
   name_ptr = get_basename(cf->filename);
 
   msg_len = strlen(name_ptr) + strlen(load_fmt) + 2;
   load_msg = g_malloc(msg_len);
   snprintf(load_msg, msg_len, load_fmt, name_ptr);
 
   name_ptr = get_basename(cf->filename);
 
   msg_len = strlen(name_ptr) + strlen(load_fmt) + 2;
   load_msg = g_malloc(msg_len);
   snprintf(load_msg, msg_len, load_fmt, name_ptr);
-  gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx, load_msg);
+  statusbar_push_file_msg(load_msg);
 
   /* Update the progress bar when it gets to this value. */
   cf->progbar_nextstep = 0;
 
   /* Update the progress bar when it gets to this value. */
   cf->progbar_nextstep = 0;
@@ -326,8 +343,7 @@ read_cap_file(capture_file *cf, int *err)
   freeze_clist(cf);
 
   stop_flag = FALSE;
   freeze_clist(cf);
 
   stop_flag = FALSE;
-  progbar = create_progress_dlg(load_msg, "Stop", &stop_flag);
-  g_free(load_msg);
+  g_get_current_time(&start_time);
 
   while ((wtap_read(cf->wth, err, &data_offset))) {
     /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
 
   while ((wtap_read(cf->wth, err, &data_offset))) {
     /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
@@ -338,7 +354,33 @@ read_cap_file(capture_file *cf, int *err)
     if (data_offset >= cf->progbar_nextstep) {
         file_pos = lseek(cf->filed, 0, SEEK_CUR);
         prog_val = (gfloat) file_pos / (gfloat) cf->f_len;
     if (data_offset >= cf->progbar_nextstep) {
         file_pos = lseek(cf->filed, 0, SEEK_CUR);
         prog_val = (gfloat) file_pos / (gfloat) cf->f_len;
-        update_progress_dlg(progbar, prog_val);
+        if (prog_val > 1.0) {
+          /* The file probably grew while we were reading it.
+             Update "cf->f_len", and try again. */
+          fd = wtap_fd(cf->wth);
+          if (fstat(fd, &cf_stat) >= 0) {
+            cf->f_len = cf_stat.st_size;
+            prog_val = (gfloat) file_pos / (gfloat) cf->f_len;
+          }
+          /* If it's still > 1, either the "fstat()" failed (in which
+             case there's not much we can do about it), or the file
+             *shrank* (in which case there's not much we can do about
+             it); just clip the progress value at 1.0. */
+          if (prog_val > 1.0)
+            prog_val = 1.0;
+        }
+        if (progbar == NULL) {
+          /* Create the progress bar if necessary */
+          progbar = delayed_create_progress_dlg("Loading", load_msg, "Stop",
+            &stop_flag, &start_time, prog_val);
+          if (progbar != NULL)
+            g_free(load_msg);
+        }
+        if (progbar != NULL) {
+          g_snprintf(status_str, sizeof(status_str), 
+                     "%luKB of %luKB", file_pos / 1024, cf->f_len / 1024);
+          update_progress_dlg(progbar, prog_val, status_str);
+        }
         cf->progbar_nextstep += cf->progbar_quantum;
     }
 
         cf->progbar_nextstep += cf->progbar_quantum;
     }
 
@@ -349,14 +391,17 @@ read_cap_file(capture_file *cf, int *err)
       destroy_progress_dlg(progbar);
       cf->state = FILE_READ_ABORTED;   /* so that we're allowed to close it */
       gtk_clist_thaw(GTK_CLIST(packet_list));  /* undo our freeze */
       destroy_progress_dlg(progbar);
       cf->state = FILE_READ_ABORTED;   /* so that we're allowed to close it */
       gtk_clist_thaw(GTK_CLIST(packet_list));  /* undo our freeze */
-      close_cap_file(cf, info_bar);
+      close_cap_file(cf);
       return (READ_ABORTED);
     }
     read_packet(cf, data_offset);
   }
 
       return (READ_ABORTED);
     }
     read_packet(cf, data_offset);
   }
 
-  /* We're done reading the file; destroy the progress bar. */
-  destroy_progress_dlg(progbar);
+  /* We're done reading the file; destroy the progress bar if it was created. */
+  if (progbar == NULL)
+    g_free(load_msg);
+  else
+    destroy_progress_dlg(progbar);
 
   /* We're done reading sequentially through the file. */
   cf->state = FILE_READ_DONE;
 
   /* We're done reading sequentially through the file. */
   cf->state = FILE_READ_DONE;
@@ -364,6 +409,10 @@ read_cap_file(capture_file *cf, int *err)
   /* Close the sequential I/O side, to free up memory it requires. */
   wtap_sequential_close(cf->wth);
 
   /* Close the sequential I/O side, to free up memory it requires. */
   wtap_sequential_close(cf->wth);
 
+  /* Allow the protocol dissectors to free up memory that they
+   * don't need after the sequential run-through of the packets. */
+  postseq_cleanup_all_protocols();
+
   /* Set the file encapsulation type now; we don't know what it is until
      we've looked at all the packets, as we don't know until then whether
      there's more than one type (and thus whether it's
   /* Set the file encapsulation type now; we don't know what it is until
      we've looked at all the packets, as we don't know until then whether
      there's more than one type (and thus whether it's
@@ -373,7 +422,7 @@ read_cap_file(capture_file *cf, int *err)
   cf->current_frame = cf->first_displayed;
   thaw_clist(cf);
 
   cf->current_frame = cf->first_displayed;
   thaw_clist(cf);
 
-  gtk_statusbar_pop(GTK_STATUSBAR(info_bar), file_ctx);
+  statusbar_pop_file_msg();
   set_display_filename(cf);
 
   /* Enable menu items that make sense if you have a capture file you've
   set_display_filename(cf);
 
   /* Enable menu items that make sense if you have a capture file you've
@@ -455,8 +504,7 @@ start_tail_cap_file(char *fname, gboolean is_tempfile, capture_file *cf)
       }
     }
 
       }
     }
 
-    gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx, 
-                      " <live capture in progress>");
+    statusbar_push_file_msg(" <live capture in progress>");
   }
   return err;
 }
   }
   return err;
 }
@@ -464,7 +512,7 @@ start_tail_cap_file(char *fname, gboolean is_tempfile, capture_file *cf)
 read_status_t
 continue_tail_cap_file(capture_file *cf, int to_read, int *err)
 {
 read_status_t
 continue_tail_cap_file(capture_file *cf, int to_read, int *err)
 {
-  int data_offset = 0;
+  long data_offset = 0;
 
   gtk_clist_freeze(GTK_CLIST(packet_list));
 
 
   gtk_clist_freeze(GTK_CLIST(packet_list));
 
@@ -505,7 +553,7 @@ continue_tail_cap_file(capture_file *cf, int to_read, int *err)
 read_status_t
 finish_tail_cap_file(capture_file *cf, int *err)
 {
 read_status_t
 finish_tail_cap_file(capture_file *cf, int *err)
 {
-  int data_offset;
+  long data_offset;
 
   gtk_clist_freeze(GTK_CLIST(packet_list));
 
 
   gtk_clist_freeze(GTK_CLIST(packet_list));
 
@@ -525,7 +573,7 @@ finish_tail_cap_file(capture_file *cf, int *err)
        it's probably exited), so we can just close the capture
        file; we return READ_ABORTED so our caller can do whatever
        is appropriate when that happens. */
        it's probably exited), so we can just close the capture
        file; we return READ_ABORTED so our caller can do whatever
        is appropriate when that happens. */
-    close_cap_file(cf, info_bar);
+    close_cap_file(cf);
     return READ_ABORTED;
   }
 
     return READ_ABORTED;
   }
 
@@ -543,6 +591,10 @@ finish_tail_cap_file(capture_file *cf, int *err)
      sequential I/O side, to free up memory it requires. */
   wtap_sequential_close(cf->wth);
 
      sequential I/O side, to free up memory it requires. */
   wtap_sequential_close(cf->wth);
 
+  /* Allow the protocol dissectors to free up memory that they
+   * don't need after the sequential run-through of the packets. */
+  postseq_cleanup_all_protocols();
+
   /* Set the file encapsulation type now; we don't know what it is until
      we've looked at all the packets, as we don't know until then whether
      there's more than one type (and thus whether it's
   /* Set the file encapsulation type now; we don't know what it is until
      we've looked at all the packets, as we don't know until then whether
      there's more than one type (and thus whether it's
@@ -550,7 +602,7 @@ finish_tail_cap_file(capture_file *cf, int *err)
   cf->lnk_t = wtap_file_encap(cf->wth);
 
   /* Pop the "<live capture in progress>" message off the status bar. */
   cf->lnk_t = wtap_file_encap(cf->wth);
 
   /* Pop the "<live capture in progress>" message off the status bar. */
-  gtk_statusbar_pop(GTK_STATUSBAR(info_bar), file_ctx);
+  statusbar_pop_file_msg();
 
   set_display_filename(cf);
 
 
   set_display_filename(cf);
 
@@ -574,9 +626,7 @@ finish_tail_cap_file(capture_file *cf, int *err)
 
 typedef struct {
   color_filter_t *colorf;
 
 typedef struct {
   color_filter_t *colorf;
-  proto_tree   *protocol_tree;
-  const guint8 *pd;
-  frame_data   *fdata;
+  epan_dissect_t *edt;
 } apply_color_filter_args;
 
 /*
 } apply_color_filter_args;
 
 /*
@@ -591,20 +641,21 @@ apply_color_filter(gpointer filter_arg, gpointer argp)
   apply_color_filter_args *args = argp;
 
   if (colorf->c_colorfilter != NULL && args->colorf == NULL) {
   apply_color_filter_args *args = argp;
 
   if (colorf->c_colorfilter != NULL && args->colorf == NULL) {
-    if (dfilter_apply(colorf->c_colorfilter, args->protocol_tree, args->pd, args->fdata->cap_len))
+    if (dfilter_apply_edt(colorf->c_colorfilter, args->edt))
       args->colorf = colorf;
   }
 }
 
 static int
 add_packet_to_packet_list(frame_data *fdata, capture_file *cf,
       args->colorf = colorf;
   }
 }
 
 static int
 add_packet_to_packet_list(frame_data *fdata, capture_file *cf,
-       union wtap_pseudo_header *pseudo_header, const u_char *buf,
+       union wtap_pseudo_header *pseudo_header, const guchar *buf,
        gboolean refilter)
 {
   apply_color_filter_args args;
        gboolean refilter)
 {
   apply_color_filter_args args;
-  gint          i, row;
-  proto_tree   *protocol_tree = NULL;
+  gint          row;
+  gboolean     create_proto_tree = FALSE;
   epan_dissect_t *edt;
   epan_dissect_t *edt;
+  GdkColor      fg, bg;
 
   /* We don't yet have a color filter to apply. */
   args.colorf = NULL;
 
   /* We don't yet have a color filter to apply. */
   args.colorf = NULL;
@@ -617,31 +668,29 @@ add_packet_to_packet_list(frame_data *fdata, capture_file *cf,
     firstusec = fdata->abs_usecs;
   }
 
     firstusec = fdata->abs_usecs;
   }
 
-  fdata->cinfo = &cf->cinfo;
-  for (i = 0; i < fdata->cinfo->num_cols; i++) {
-    fdata->cinfo->col_data[i][0] = '\0';
-  }
-
   /* If either
 
        we have a display filter and are re-applying it;
 
        we have a list of color filters;
 
   /* If either
 
        we have a display filter and are re-applying it;
 
        we have a list of color filters;
 
-       we have plugins to apply;
-
      allocate a protocol tree root node, so that we'll construct
      a protocol tree against which a filter expression can be
      evaluated. */
      allocate a protocol tree root node, so that we'll construct
      a protocol tree against which a filter expression can be
      evaluated. */
-  if ((cf->dfcode != NULL && refilter) || filter_list != NULL
-#ifdef HAVE_PLUGINS
-       || enabled_plugins_number > 0
-#endif
-       )
-    protocol_tree = proto_tree_create_root();
+  if ((cf->dfcode != NULL && refilter) || filter_list != NULL)
+         create_proto_tree = TRUE;
 
   /* Dissect the frame. */
 
   /* Dissect the frame. */
-  edt = epan_dissect_new(pseudo_header, buf, fdata, protocol_tree);
+  edt = epan_dissect_new(create_proto_tree, FALSE);
+
+  if (cf->dfcode != NULL && refilter) {
+      epan_dissect_prime_dfilter(edt, cf->dfcode);
+  }
+  if (filter_list) {
+      filter_list_prime_edt(edt);
+  }
+  epan_dissect_run(edt, pseudo_header, buf, fdata, &cf->cinfo);
+
 
   /* If we have a display filter, apply it if we're refiltering, otherwise
      leave the "passed_dfilter" flag alone.
 
   /* If we have a display filter, apply it if we're refiltering, otherwise
      leave the "passed_dfilter" flag alone.
@@ -650,7 +699,7 @@ add_packet_to_packet_list(frame_data *fdata, capture_file *cf,
   if (cf->dfcode != NULL) {
     if (refilter) {
       if (cf->dfcode != NULL)
   if (cf->dfcode != NULL) {
     if (refilter) {
       if (cf->dfcode != NULL)
-        fdata->flags.passed_dfilter = dfilter_apply(cf->dfcode, protocol_tree, buf, fdata->cap_len) ? 1 : 0;
+        fdata->flags.passed_dfilter = dfilter_apply_edt(cf->dfcode, edt) ? 1 : 0;
       else
         fdata->flags.passed_dfilter = 1;
     }
       else
         fdata->flags.passed_dfilter = 1;
     }
@@ -661,19 +710,11 @@ add_packet_to_packet_list(frame_data *fdata, capture_file *cf,
      the color filters. */
   if (fdata->flags.passed_dfilter) {
     if (filter_list != NULL) {
      the color filters. */
   if (fdata->flags.passed_dfilter) {
     if (filter_list != NULL) {
-      args.protocol_tree = protocol_tree;
-      args.pd = buf;
-      args.fdata = fdata;
+      args.edt = edt;
       g_slist_foreach(filter_list, apply_color_filter, &args);
     }
   }
 
       g_slist_foreach(filter_list, apply_color_filter, &args);
     }
   }
 
-  /* There are no more filters to apply, so we don't need any protocol
-     tree; free it if we created it. */
-  if (protocol_tree != NULL)
-    proto_tree_free(protocol_tree);
-
-  epan_dissect_free(edt);
 
   if (fdata->flags.passed_dfilter) {
     /* This frame passed the display filter, so add it to the clist. */
 
   if (fdata->flags.passed_dfilter) {
     /* This frame passed the display filter, so add it to the clist. */
@@ -694,8 +735,8 @@ add_packet_to_packet_list(frame_data *fdata, capture_file *cf,
     /* If it's greater than the current elapsed time, set the elapsed time
        to it (we check for "greater than" so as not to be confused by
        time moving backwards). */
     /* If it's greater than the current elapsed time, set the elapsed time
        to it (we check for "greater than" so as not to be confused by
        time moving backwards). */
-    if (cf->esec < fdata->rel_secs
-       || (cf->esec == fdata->rel_secs && cf->eusec < fdata->rel_usecs)) {
+    if ((gint32)cf->esec < fdata->rel_secs
+       || ((gint32)cf->esec == fdata->rel_secs && (gint32)cf->eusec < fdata->rel_usecs)) {
       cf->esec = fdata->rel_secs;
       cf->eusec = fdata->rel_usecs;
     }
       cf->esec = fdata->rel_secs;
       cf->eusec = fdata->rel_usecs;
     }
@@ -707,7 +748,7 @@ add_packet_to_packet_list(frame_data *fdata, capture_file *cf,
     prevsec = fdata->abs_secs;
     prevusec = fdata->abs_usecs;
 
     prevsec = fdata->abs_secs;
     prevusec = fdata->abs_usecs;
 
-    fill_in_columns(fdata);
+    epan_dissect_fill_in_columns(edt);
 
     /* If we haven't yet seen the first frame, this is it.
 
 
     /* If we haven't yet seen the first frame, this is it.
 
@@ -728,39 +769,38 @@ add_packet_to_packet_list(frame_data *fdata, capture_file *cf,
     /* This is the last frame we've seen so far. */
     cf->last_displayed = fdata;
 
     /* This is the last frame we've seen so far. */
     cf->last_displayed = fdata;
 
-    row = gtk_clist_append(GTK_CLIST(packet_list), fdata->cinfo->col_data);
+    row = gtk_clist_append(GTK_CLIST(packet_list), cf->cinfo.col_data);
     gtk_clist_set_row_data(GTK_CLIST(packet_list), row, fdata);
 
     if (fdata->flags.marked) {
     gtk_clist_set_row_data(GTK_CLIST(packet_list), row, fdata);
 
     if (fdata->flags.marked) {
-       gtk_clist_set_background(GTK_CLIST(packet_list), row, &prefs.gui_marked_bg);
-       gtk_clist_set_foreground(GTK_CLIST(packet_list), row, &prefs.gui_marked_fg);
+       color_t_to_gdkcolor(&bg, &prefs.gui_marked_bg);
+       color_t_to_gdkcolor(&fg, &prefs.gui_marked_fg);
     } else if (filter_list != NULL && (args.colorf != NULL)) {
     } else if (filter_list != NULL && (args.colorf != NULL)) {
-        gtk_clist_set_background(GTK_CLIST(packet_list), row,
-                   &args.colorf->bg_color);
-        gtk_clist_set_foreground(GTK_CLIST(packet_list), row,
-                   &args.colorf->fg_color);
+       bg = args.colorf->bg_color;
+       fg = args.colorf->fg_color;
     } else {
     } else {
-        gtk_clist_set_background(GTK_CLIST(packet_list), row, &WHITE);
-        gtk_clist_set_foreground(GTK_CLIST(packet_list), row, &BLACK);
+       bg = WHITE;
+       fg = BLACK;
     }
     }
+    gtk_clist_set_background(GTK_CLIST(packet_list), row, &bg);
+    gtk_clist_set_foreground(GTK_CLIST(packet_list), row, &fg);
   } else {
     /* This frame didn't pass the display filter, so it's not being added
        to the clist, and thus has no row. */
     row = -1;
   }
   } else {
     /* This frame didn't pass the display filter, so it's not being added
        to the clist, and thus has no row. */
     row = -1;
   }
-  fdata->cinfo = NULL;
+  epan_dissect_free(edt);
   return row;
 }
 
 static void
   return row;
 }
 
 static void
-read_packet(capture_file *cf, int offset)
+read_packet(capture_file *cf, long offset)
 {
   const struct wtap_pkthdr *phdr = wtap_phdr(cf->wth);
   union wtap_pseudo_header *pseudo_header = wtap_pseudoheader(cf->wth);
 {
   const struct wtap_pkthdr *phdr = wtap_phdr(cf->wth);
   union wtap_pseudo_header *pseudo_header = wtap_pseudoheader(cf->wth);
-  const u_char *buf = wtap_buf_ptr(cf->wth);
+  const guchar *buf = wtap_buf_ptr(cf->wth);
   frame_data   *fdata;
   int           passed;
   frame_data   *fdata;
   int           passed;
-  proto_tree   *protocol_tree;
   frame_data   *plist_end;
   epan_dissect_t *edt;
 
   frame_data   *plist_end;
   epan_dissect_t *edt;
 
@@ -779,14 +819,13 @@ read_packet(capture_file *cf, int offset)
   fdata->flags.encoding = CHAR_ASCII;
   fdata->flags.visited = 0;
   fdata->flags.marked = 0;
   fdata->flags.encoding = CHAR_ASCII;
   fdata->flags.visited = 0;
   fdata->flags.marked = 0;
-  fdata->cinfo = NULL;
 
   passed = TRUE;
   if (cf->rfcode) {
 
   passed = TRUE;
   if (cf->rfcode) {
-    protocol_tree = proto_tree_create_root();
-    edt = epan_dissect_new(pseudo_header, buf, fdata, protocol_tree);
-    passed = dfilter_apply(cf->rfcode, protocol_tree, buf, fdata->cap_len);
-    proto_tree_free(protocol_tree);
+    edt = epan_dissect_new(TRUE, FALSE);
+    epan_dissect_prime_dfilter(edt, cf->rfcode);
+    epan_dissect_run(edt, pseudo_header, buf, fdata, NULL);
+    passed = dfilter_apply_edt(cf->rfcode, edt);
     epan_dissect_free(edt);
   }   
   if (passed) {
     epan_dissect_free(edt);
   }   
   if (passed) {
@@ -817,16 +856,18 @@ read_packet(capture_file *cf, int offset)
 int
 filter_packets(capture_file *cf, gchar *dftext)
 {
 int
 filter_packets(capture_file *cf, gchar *dftext)
 {
-  dfilter *dfcode;
+  dfilter_t *dfcode;
 
   if (dftext == NULL) {
     /* The new filter is an empty filter (i.e., display all packets). */
     dfcode = NULL;
   } else {
     /*
 
   if (dftext == NULL) {
     /* The new filter is an empty filter (i.e., display all packets). */
     dfcode = NULL;
   } else {
     /*
-     * We have a filter; try to compile it.
+     * We have a filter; make a copy of it (as we'll be saving it),
+     * and try to compile it.
      */
      */
-    if (dfilter_compile(dftext, &dfcode) != 0) {
+    dftext = g_strdup(dftext);
+    if (!dfilter_compile(dftext, &dfcode)) {
       /* The attempt failed; report an error. */
       simple_dialog(ESD_TYPE_CRIT, NULL, dfilter_error_msg);
       return 0;
       /* The attempt failed; report an error. */
       simple_dialog(ESD_TYPE_CRIT, NULL, dfilter_error_msg);
       return 0;
@@ -845,25 +886,29 @@ filter_packets(capture_file *cf, gchar *dftext)
     g_free(cf->dfilter);
   cf->dfilter = dftext;
   if (cf->dfcode != NULL)
     g_free(cf->dfilter);
   cf->dfilter = dftext;
   if (cf->dfcode != NULL)
-    dfilter_destroy(cf->dfcode);
+    dfilter_free(cf->dfcode);
   cf->dfcode = dfcode;
 
   /* Now rescan the packet list, applying the new filter, but not
      throwing away information constructed on a previous pass. */
   cf->dfcode = dfcode;
 
   /* Now rescan the packet list, applying the new filter, but not
      throwing away information constructed on a previous pass. */
-  rescan_packets(cf, "Filtering", TRUE, FALSE);
+  if (dftext == NULL) {
+    rescan_packets(cf, "Resetting", "Filter", TRUE, FALSE);
+  } else {
+    rescan_packets(cf, "Filtering", dftext, TRUE, FALSE);
+  }
   return 1;
 }
 
 void
 colorize_packets(capture_file *cf)
 {
   return 1;
 }
 
 void
 colorize_packets(capture_file *cf)
 {
-  rescan_packets(cf, "Colorizing", FALSE, FALSE);
+  rescan_packets(cf, "Colorizing", "all frames", FALSE, FALSE);
 }
 
 void
 redissect_packets(capture_file *cf)
 {
 }
 
 void
 redissect_packets(capture_file *cf)
 {
-  rescan_packets(cf, "Reprocessing", TRUE, TRUE);
+  rescan_packets(cf, "Reprocessing", "all frames", TRUE, TRUE);
 }
 
 /* Rescan the list of packets, reconstructing the CList.
 }
 
 /* Rescan the list of packets, reconstructing the CList.
@@ -871,6 +916,9 @@ redissect_packets(capture_file *cf)
    "action" describes why we're doing this; it's used in the progress
    dialog box.
 
    "action" describes why we're doing this; it's used in the progress
    dialog box.
 
+   "action_item" describes what we're doing; it's used in the progress
+   dialog box.
+
    "refilter" is TRUE if we need to re-evaluate the filter expression.
 
    "redissect" is TRUE if we need to make the dissectors reconstruct
    "refilter" is TRUE if we need to re-evaluate the filter expression.
 
    "redissect" is TRUE if we need to make the dissectors reconstruct
@@ -878,18 +926,20 @@ redissect_packets(capture_file *cf)
    some dissector has changed, meaning some dissector might construct
    its state differently from the way it was constructed the last time). */
 static void
    some dissector has changed, meaning some dissector might construct
    its state differently from the way it was constructed the last time). */
 static void
-rescan_packets(capture_file *cf, const char *action, gboolean refilter,
-               gboolean redissect)
+rescan_packets(capture_file *cf, const char *action, const char *action_item,
+               gboolean refilter, gboolean redissect)
 {
   frame_data *fdata;
 {
   frame_data *fdata;
-  progdlg_t *progbar;
-  gboolean stop_flag;
-  guint32 progbar_quantum;
-  guint32 progbar_nextstep;
-  int count;
+  progdlg_t  *progbar = NULL;
+  gboolean    stop_flag;
+  int         count;
+  int         err;
   frame_data *selected_frame;
   frame_data *selected_frame;
-  int selected_row;
-  int row;
+  int         selected_row;
+  int         row;
+  float       prog_val;
+  GTimeVal    start_time;
+  gchar       status_str[100];
 
   /* Which frame, if any, is the currently selected frame?
      XXX - should the selected frame or the focus frame be the "current"
 
   /* Which frame, if any, is the currently selected frame?
      XXX - should the selected frame or the focus frame be the "current"
@@ -907,11 +957,8 @@ rescan_packets(capture_file *cf, const char *action, gboolean refilter,
        which might cause the state information to be constructed differently
        by that dissector. */
 
        which might cause the state information to be constructed differently
        by that dissector. */
 
-    /* Initialize the table of conversations. */
-    epan_conversation_init();
-
-    /* Initialize protocol-specific variables */
-    init_all_protocols();
+    /* Initialize all data structures used for dissection. */
+    init_dissection();
   }
 
   /* Freeze the packet list while we redo it, so we don't get any
   }
 
   /* Freeze the packet list while we redo it, so we don't get any
@@ -934,15 +981,15 @@ rescan_packets(capture_file *cf, const char *action, gboolean refilter,
   prevusec = 0;
 
   /* Update the progress bar when it gets to this value. */
   prevusec = 0;
 
   /* Update the progress bar when it gets to this value. */
-  progbar_nextstep = 0;
+  cf->progbar_nextstep = 0;
   /* When we reach the value that triggers a progress bar update,
      bump that value by this amount. */
   /* When we reach the value that triggers a progress bar update,
      bump that value by this amount. */
-  progbar_quantum = cf->count/N_PROGBAR_UPDATES;
+  cf->progbar_quantum = cf->count/N_PROGBAR_UPDATES;
   /* Count of packets at which we've looked. */
   count = 0;
 
   stop_flag = FALSE;
   /* Count of packets at which we've looked. */
   count = 0;
 
   stop_flag = FALSE;
-  progbar = create_progress_dlg(action, "Stop", &stop_flag);
+  g_get_current_time(&start_time);
 
   for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
     /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
 
   for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
     /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
@@ -950,15 +997,25 @@ rescan_packets(capture_file *cf, const char *action, gboolean refilter,
        to repaint what's pending, and doing so may involve an "ioctl()"
        to see if there's any pending input from an X server, and doing
        that for every packet can be costly, especially on a big file. */
        to repaint what's pending, and doing so may involve an "ioctl()"
        to see if there's any pending input from an X server, and doing
        that for every packet can be costly, especially on a big file. */
-    if (count >= progbar_nextstep) {
+    if (count >= cf->progbar_nextstep) {
       /* let's not divide by zero. I should never be started
        * with count == 0, so let's assert that
        */
       g_assert(cf->count > 0);
       /* let's not divide by zero. I should never be started
        * with count == 0, so let's assert that
        */
       g_assert(cf->count > 0);
+      prog_val = (gfloat) count / cf->count;
 
 
-      update_progress_dlg(progbar, (gfloat) count / cf->count);
+      if (progbar == NULL)
+        /* Create the progress bar if necessary */
+        progbar = delayed_create_progress_dlg(action, action_item, "Stop", &stop_flag,
+          &start_time, prog_val);
 
 
-      progbar_nextstep += progbar_quantum;
+      if (progbar != NULL) {
+        g_snprintf(status_str, sizeof(status_str),
+                  "%4u of %u frames", count, cf->count);
+        update_progress_dlg(progbar, prog_val, status_str);
+      }
+
+      cf->progbar_nextstep += cf->progbar_quantum;
     }
 
     if (stop_flag) {
     }
 
     if (stop_flag) {
@@ -983,16 +1040,17 @@ rescan_packets(capture_file *cf, const char *action, gboolean refilter,
       /* Since all state for the frame was destroyed, mark the frame
        * as not visited, free the GSList referring to the state
        * data (the per-frame data itself was freed by
       /* Since all state for the frame was destroyed, mark the frame
        * as not visited, free the GSList referring to the state
        * data (the per-frame data itself was freed by
-       * "init_all_protocols()"), and null out the GSList pointer. */
+       * "init_dissection()"), and null out the GSList pointer. */
       fdata->flags.visited = 0;
       if (fdata->pfd) {
        g_slist_free(fdata->pfd);
       fdata->flags.visited = 0;
       if (fdata->pfd) {
        g_slist_free(fdata->pfd);
+        fdata->pfd = NULL;
       }
       }
-      fdata->pfd = NULL;
     }
 
     }
 
+    /* XXX - do something with "err" */
     wtap_seek_read (cf->wth, fdata->file_off, &cf->pseudo_header,
     wtap_seek_read (cf->wth, fdata->file_off, &cf->pseudo_header,
-       cf->pd, fdata->cap_len);
+       cf->pd, fdata->cap_len, &err);
 
     row = add_packet_to_packet_list(fdata, cf, &cf->pseudo_header, cf->pd,
                                        refilter);
 
     row = add_packet_to_packet_list(fdata, cf, &cf->pseudo_header, cf->pd,
                                        refilter);
@@ -1014,13 +1072,15 @@ rescan_packets(capture_file *cf, const char *action, gboolean refilter,
       fdata->flags.visited = 0;
       if (fdata->pfd) {
        g_slist_free(fdata->pfd);
       fdata->flags.visited = 0;
       if (fdata->pfd) {
        g_slist_free(fdata->pfd);
+        fdata->pfd = NULL;
       }
       }
-      fdata->pfd = NULL;
     }
   }
 
     }
   }
 
-  /* We're done filtering the packets; destroy the progress bar. */
-  destroy_progress_dlg(progbar);
+  /* We're done filtering the packets; destroy the progress bar if it
+     was created. */
+  if (progbar != NULL)
+    destroy_progress_dlg(progbar);
 
   /* Unfreeze the packet list. */
   gtk_clist_thaw(GTK_CLIST(packet_list));
 
   /* Unfreeze the packet list. */
   gtk_clist_thaw(GTK_CLIST(packet_list));
@@ -1043,12 +1103,10 @@ print_packets(capture_file *cf, print_args_t *print_args)
 {
   int         i;
   frame_data *fdata;
 {
   int         i;
   frame_data *fdata;
-  progdlg_t  *progbar;
+  progdlg_t  *progbar = NULL;
   gboolean    stop_flag;
   gboolean    stop_flag;
-  guint32     progbar_quantum;
-  guint32     progbar_nextstep;
-  guint32     count;
-  proto_tree *protocol_tree;
+  int         count;
+  int         err;
   gint       *col_widths = NULL;
   gint        data_width;
   gboolean    print_separator;
   gint       *col_widths = NULL;
   gint        data_width;
   gboolean    print_separator;
@@ -1058,6 +1116,9 @@ print_packets(capture_file *cf, print_args_t *print_args)
   int         column_len;
   int         line_len;
   epan_dissect_t *edt = NULL;
   int         column_len;
   int         line_len;
   epan_dissect_t *edt = NULL;
+  float       prog_val;
+  GTimeVal    start_time;
+  gchar       status_str[100];
 
   cf->print_fh = open_print_dest(print_args->to_file, print_args->dest);
   if (cf->print_fh == NULL)
 
   cf->print_fh = open_print_dest(print_args->to_file, print_args->dest);
   if (cf->print_fh == NULL)
@@ -1094,7 +1155,7 @@ print_packets(capture_file *cf, print_args_t *print_args)
 
       /* Make sure there's room in the line buffer for the column; if not,
          double its length. */
 
       /* Make sure there's room in the line buffer for the column; if not,
          double its length. */
-      line_len += column_len + 1;      /* "+1" for space or \n */
+      line_len += column_len + 1;      /* "+1" for space */
       if (line_len > line_buf_len) {
         line_buf_len *= 2;
         line_buf = g_realloc(line_buf, line_buf_len + 1);
       if (line_len > line_buf_len) {
         line_buf_len *= 2;
         line_buf = g_realloc(line_buf, line_buf_len + 1);
@@ -1106,31 +1167,25 @@ print_packets(capture_file *cf, print_args_t *print_args)
       else
         sprintf(cp, "%-*s", col_widths[i], cf->cinfo.col_title[i]);
       cp += column_len;
       else
         sprintf(cp, "%-*s", col_widths[i], cf->cinfo.col_title[i]);
       cp += column_len;
-      if (i == cf->cinfo.num_cols - 1)
-        *cp++ = '\n';
-      else
+      if (i != cf->cinfo.num_cols - 1)
         *cp++ = ' ';
     }
     *cp = '\0';
         *cp++ = ' ';
     }
     *cp = '\0';
-    print_line(cf->print_fh, print_args->format, line_buf);
+    print_line(cf->print_fh, 0, print_args->format, line_buf);
   }
 
   print_separator = FALSE;
 
   }
 
   print_separator = FALSE;
 
-  /* The protocol tree will be "visible", i.e., printed, only if we're
-     not printing a summary. */
-  proto_tree_is_visible = !print_args->print_summary;
-
   /* Update the progress bar when it gets to this value. */
   /* Update the progress bar when it gets to this value. */
-  progbar_nextstep = 0;
+  cf->progbar_nextstep = 0;
   /* When we reach the value that triggers a progress bar update,
      bump that value by this amount. */
   /* When we reach the value that triggers a progress bar update,
      bump that value by this amount. */
-  progbar_quantum = cf->count/N_PROGBAR_UPDATES;
+  cf->progbar_quantum = cf->count/N_PROGBAR_UPDATES;
   /* Count of packets at which we've looked. */
   count = 0;
 
   stop_flag = FALSE;
   /* Count of packets at which we've looked. */
   count = 0;
 
   stop_flag = FALSE;
-  progbar = create_progress_dlg("Printing", "Stop", &stop_flag);
+  g_get_current_time(&start_time);
 
   /* Iterate through the list of packets, printing the packets that
      were selected by the current display filter.  */
 
   /* Iterate through the list of packets, printing the packets that
      were selected by the current display filter.  */
@@ -1140,15 +1195,25 @@ print_packets(capture_file *cf, print_args_t *print_args)
        to repaint what's pending, and doing so may involve an "ioctl()"
        to see if there's any pending input from an X server, and doing
        that for every packet can be costly, especially on a big file. */
        to repaint what's pending, and doing so may involve an "ioctl()"
        to see if there's any pending input from an X server, and doing
        that for every packet can be costly, especially on a big file. */
-    if (count >= progbar_nextstep) {
+    if (count >= cf->progbar_nextstep) {
       /* let's not divide by zero. I should never be started
        * with count == 0, so let's assert that
        */
       g_assert(cf->count > 0);
       /* let's not divide by zero. I should never be started
        * with count == 0, so let's assert that
        */
       g_assert(cf->count > 0);
+      prog_val = (gfloat) count / cf->count;
 
 
-      update_progress_dlg(progbar, (gfloat) count / cf->count);
+      if (progbar == NULL)
+        /* Create the progress bar if necessary */
+        progbar = delayed_create_progress_dlg("Printing", "selected frames", "Stop", &stop_flag,
+          &start_time, prog_val);
 
 
-      progbar_nextstep += progbar_quantum;
+      if (progbar != NULL) {
+        g_snprintf(status_str, sizeof(status_str),
+                   "%4u of %u frames", count, cf->count);
+        update_progress_dlg(progbar, prog_val, status_str);
+      }
+
+      cf->progbar_nextstep += cf->progbar_quantum;
     }
 
     if (stop_flag) {
     }
 
     if (stop_flag) {
@@ -1162,19 +1227,20 @@ print_packets(capture_file *cf, print_args_t *print_args)
     }
 
     count++;
     }
 
     count++;
-
-    if (fdata->flags.passed_dfilter) {
+    /* Check to see if we are suppressing unmarked packets, if so, 
+     * suppress them and then proceed to check for visibility.
+     */
+    if (((print_args->suppress_unmarked && fdata->flags.marked ) ||
+        !(print_args->suppress_unmarked)) && fdata->flags.passed_dfilter) {
+      /* XXX - do something with "err" */
       wtap_seek_read (cf->wth, fdata->file_off, &cf->pseudo_header,
       wtap_seek_read (cf->wth, fdata->file_off, &cf->pseudo_header,
-                       cf->pd, fdata->cap_len);
+                       cf->pd, fdata->cap_len, &err);
       if (print_args->print_summary) {
         /* Fill in the column information, but don't bother creating
            the logical protocol tree. */
       if (print_args->print_summary) {
         /* Fill in the column information, but don't bother creating
            the logical protocol tree. */
-        fdata->cinfo = &cf->cinfo;
-        for (i = 0; i < fdata->cinfo->num_cols; i++) {
-          fdata->cinfo->col_data[i][0] = '\0';
-        }
-        edt = epan_dissect_new(&cf->pseudo_header, cf->pd, fdata, NULL);
-        fill_in_columns(fdata);
+        edt = epan_dissect_new(FALSE, FALSE);
+        epan_dissect_run(edt, &cf->pseudo_header, cf->pd, fdata, &cf->cinfo);
+        epan_dissect_fill_in_columns(edt);
         cp = &line_buf[0];
         line_len = 0;
         for (i = 0; i < cf->cinfo.num_cols; i++) {
         cp = &line_buf[0];
         line_len = 0;
         for (i = 0; i < cf->cinfo.num_cols; i++) {
@@ -1185,7 +1251,7 @@ print_packets(capture_file *cf, print_args_t *print_args)
 
           /* Make sure there's room in the line buffer for the column; if not,
              double its length. */
 
           /* Make sure there's room in the line buffer for the column; if not,
              double its length. */
-          line_len += column_len + 1;  /* "+1" for space or \n */
+          line_len += column_len + 1;  /* "+1" for space */
           if (line_len > line_buf_len) {
             line_buf_len *= 2;
             line_buf = g_realloc(line_buf, line_buf_len + 1);
           if (line_len > line_buf_len) {
             line_buf_len *= 2;
             line_buf = g_realloc(line_buf, line_buf_len + 1);
@@ -1197,31 +1263,27 @@ print_packets(capture_file *cf, print_args_t *print_args)
           else
             sprintf(cp, "%-*s", col_widths[i], cf->cinfo.col_data[i]);
           cp += column_len;
           else
             sprintf(cp, "%-*s", col_widths[i], cf->cinfo.col_data[i]);
           cp += column_len;
-          if (i == cf->cinfo.num_cols - 1)
-            *cp++ = '\n';
-          else
+          if (i != cf->cinfo.num_cols - 1)
             *cp++ = ' ';
         }
         *cp = '\0';
             *cp++ = ' ';
         }
         *cp = '\0';
-        print_line(cf->print_fh, print_args->format, line_buf);
+        print_line(cf->print_fh, 0, print_args->format, line_buf);
       } else {
         if (print_separator)
       } else {
         if (print_separator)
-          print_line(cf->print_fh, print_args->format, "\n");
+          print_line(cf->print_fh, 0, print_args->format, "");
 
 
-        /* Create the logical protocol tree. */
-        protocol_tree = proto_tree_create_root();
-        edt = epan_dissect_new(&cf->pseudo_header, cf->pd, fdata, protocol_tree);
+        /* Create the logical protocol tree, complete with the display
+           representation of the items; we don't need the columns here,
+           however. */
+        edt = epan_dissect_new(TRUE, TRUE);
+        epan_dissect_run(edt, &cf->pseudo_header, cf->pd, fdata, NULL);
 
         /* Print the information in that tree. */
 
         /* Print the information in that tree. */
-        proto_tree_print(FALSE, print_args, (GNode *)protocol_tree,
-                       cf->pd, fdata, cf->print_fh);
-
-        proto_tree_free(protocol_tree);
+        proto_tree_print(print_args, edt, cf->print_fh);
 
        if (print_args->print_hex) {
          /* Print the full packet data as hex. */
 
        if (print_args->print_hex) {
          /* Print the full packet data as hex. */
-         print_hex_data(cf->print_fh, print_args->format, cf->pd,
-                       fdata->cap_len, fdata->flags.encoding);
+         print_hex_data(cf->print_fh, print_args->format, edt);
        }
 
         /* Print a blank line if we print anything after this. */
        }
 
         /* Print a blank line if we print anything after this. */
@@ -1231,8 +1293,10 @@ print_packets(capture_file *cf, print_args_t *print_args)
     }
   }
 
     }
   }
 
-  /* We're done printing the packets; destroy the progress bar. */
-  destroy_progress_dlg(progbar);
+  /* We're done printing the packets; destroy the progress bar if
+     it was created. */
+  if (progbar != NULL)
+    destroy_progress_dlg(progbar);
 
   if (col_widths != NULL)
     g_free(col_widths);
 
   if (col_widths != NULL)
     g_free(col_widths);
@@ -1245,8 +1309,6 @@ print_packets(capture_file *cf, print_args_t *print_args)
  
   cf->print_fh = NULL;
 
  
   cf->print_fh = NULL;
 
-  proto_tree_is_visible = FALSE;
-
   return TRUE;
 }
 
   return TRUE;
 }
 
@@ -1257,29 +1319,42 @@ void
 change_time_formats(capture_file *cf)
 {
   frame_data *fdata;
 change_time_formats(capture_file *cf)
 {
   frame_data *fdata;
-  progdlg_t *progbar;
-  gboolean stop_flag;
-  guint32 progbar_quantum;
-  guint32 progbar_nextstep;
-  int count;
-  int row;
-  int i;
-  GtkStyle  *pl_style;
+  progdlg_t  *progbar = NULL;
+  gboolean    stop_flag;
+  int         count;
+  int         row;
+  int         i;
+  GtkStyle   *pl_style;
+  float       prog_val;
+  GTimeVal    start_time;
+  gchar       status_str[100];
+
+  /* Are there any columns with time stamps in the "command-line-specified"
+     format?
+
+     XXX - we have to force the "column is writable" flag on, as it
+     might be off from the last frame that was dissected. */
+  col_set_writable(&cf->cinfo, TRUE);
+  if (!check_col(&cf->cinfo, COL_CLS_TIME)) {
+    /* No, there aren't any columns in that format, so we have no work
+       to do. */
+    return;
+  }
 
   /* Freeze the packet list while we redo it, so we don't get any
      screen updates while it happens. */
   freeze_clist(cf);
 
   /* Update the progress bar when it gets to this value. */
 
   /* Freeze the packet list while we redo it, so we don't get any
      screen updates while it happens. */
   freeze_clist(cf);
 
   /* Update the progress bar when it gets to this value. */
-  progbar_nextstep = 0;
+  cf->progbar_nextstep = 0;
   /* When we reach the value that triggers a progress bar update,
      bump that value by this amount. */
   /* When we reach the value that triggers a progress bar update,
      bump that value by this amount. */
-  progbar_quantum = cf->count/N_PROGBAR_UPDATES;
+  cf->progbar_quantum = cf->count/N_PROGBAR_UPDATES;
   /* Count of packets at which we've looked. */
   count = 0;
 
   stop_flag = FALSE;
   /* Count of packets at which we've looked. */
   count = 0;
 
   stop_flag = FALSE;
-  progbar = create_progress_dlg("Changing time display", "Stop", &stop_flag);
+  g_get_current_time(&start_time);
 
   /* Iterate through the list of packets, checking whether the packet
      is in a row of the summary list and, if so, whether there are
 
   /* Iterate through the list of packets, checking whether the packet
      is in a row of the summary list and, if so, whether there are
@@ -1291,15 +1366,26 @@ change_time_formats(capture_file *cf)
        to repaint what's pending, and doing so may involve an "ioctl()"
        to see if there's any pending input from an X server, and doing
        that for every packet can be costly, especially on a big file. */
        to repaint what's pending, and doing so may involve an "ioctl()"
        to see if there's any pending input from an X server, and doing
        that for every packet can be costly, especially on a big file. */
-    if (count >= progbar_nextstep) {
+    if (count >= cf->progbar_nextstep) {
       /* let's not divide by zero. I should never be started
        * with count == 0, so let's assert that
        */
       g_assert(cf->count > 0);
 
       /* let's not divide by zero. I should never be started
        * with count == 0, so let's assert that
        */
       g_assert(cf->count > 0);
 
-      update_progress_dlg(progbar, (gfloat) count / cf->count);
+      prog_val = (gfloat) count / cf->count;
+
+      if (progbar == NULL)
+        /* Create the progress bar if necessary */
+        progbar = delayed_create_progress_dlg("Changing", "time display", "Stop",
+          &stop_flag, &start_time, prog_val);
+
+      if (progbar != NULL) {
+        g_snprintf(status_str, sizeof(status_str),
+                   "%4u of %u frames", count, cf->count);
+        update_progress_dlg(progbar, prog_val, status_str);
+      }
 
 
-      progbar_nextstep += progbar_quantum;
+      cf->progbar_nextstep += cf->progbar_quantum;
     }
 
     if (stop_flag) {
     }
 
     if (stop_flag) {
@@ -1319,30 +1405,23 @@ change_time_formats(capture_file *cf)
     if (row != -1) {
       /* This packet is in the summary list, on row "row". */
 
     if (row != -1) {
       /* This packet is in the summary list, on row "row". */
 
-      /* XXX - there really should be a way of checking "cf->cinfo" for this;
-         the answer isn't going to change from packet to packet, so we should
-         simply skip all the "change_time_formats()" work if we're not
-         changing anything. */
-      fdata->cinfo = &cf->cinfo;
-      if (check_col(fdata, COL_CLS_TIME)) {
-        /* There are columns that show the time in the "command-line-specified"
-           format; update them. */
-        for (i = 0; i < cf->cinfo.num_cols; i++) {
-          if (cf->cinfo.fmt_matx[i][COL_CLS_TIME]) {
-            /* This is one of the columns that shows the time in
-               "command-line-specified" format; update it. */
-            cf->cinfo.col_data[i][0] = '\0';
-            col_set_cls_time(fdata, i);
-            gtk_clist_set_text(GTK_CLIST(packet_list), row, i,
-                         cf->cinfo.col_data[i]);
-         }
+      for (i = 0; i < cf->cinfo.num_cols; i++) {
+        if (cf->cinfo.fmt_matx[i][COL_CLS_TIME]) {
+          /* This is one of the columns that shows the time in
+             "command-line-specified" format; update it. */
+          cf->cinfo.col_buf[i][0] = '\0';
+          col_set_cls_time(fdata, &cf->cinfo, i);
+          gtk_clist_set_text(GTK_CLIST(packet_list), row, i,
+                            cf->cinfo.col_data[i]);
         }
       }
     }
   }
 
         }
       }
     }
   }
 
-  /* We're done redisplaying the packets; destroy the progress bar. */
-  destroy_progress_dlg(progbar);
+  /* We're done redisplaying the packets; destroy the progress bar if it
+     was created. */
+  if (progbar != NULL)
+    destroy_progress_dlg(progbar);
 
   /* Set the column widths of those columns that show the time in
      "command-line-specified" format. */
 
   /* Set the column widths of those columns that show the time in
      "command-line-specified" format. */
@@ -1358,36 +1437,22 @@ change_time_formats(capture_file *cf)
   thaw_clist(cf);
 }
 
   thaw_clist(cf);
 }
 
-static void
-clear_tree_and_hex_views(void)
-{
-  /* Clear the hex dump. */
-  gtk_text_freeze(GTK_TEXT(byte_view));
-  gtk_text_set_point(GTK_TEXT(byte_view), 0);
-  gtk_text_forward_delete(GTK_TEXT(byte_view),
-    gtk_text_get_length(GTK_TEXT(byte_view)));
-  gtk_text_thaw(GTK_TEXT(byte_view));
-
-  /* Remove all nodes in ctree. This is how it's done in testgtk.c in GTK+ */
-  gtk_clist_clear ( GTK_CLIST(tree_view) );
-
-}
-
 gboolean
 gboolean
-find_packet(capture_file *cf, dfilter *sfcode)
+find_packet(capture_file *cf, dfilter_t *sfcode)
 {
   frame_data *start_fd;
   frame_data *fdata;
   frame_data *new_fd = NULL;
 {
   frame_data *start_fd;
   frame_data *fdata;
   frame_data *new_fd = NULL;
-  progdlg_t *progbar;
-  gboolean stop_flag;
-  guint32 progbar_quantum;
-  guint32 progbar_nextstep;
-  int count;
-  proto_tree *protocol_tree;
-  gboolean frame_matched;
-  int row;
+  progdlg_t  *progbar = NULL;
+  gboolean    stop_flag;
+  int         count;
+  int         err;
+  gboolean    frame_matched;
+  int         row;
   epan_dissect_t       *edt;
   epan_dissect_t       *edt;
+  float       prog_val;
+  GTimeVal    start_time;
+  gchar       status_str[100];
 
   start_fd = cf->current_frame;
   if (start_fd != NULL)  {
 
   start_fd = cf->current_frame;
   if (start_fd != NULL)  {
@@ -1397,14 +1462,13 @@ find_packet(capture_file *cf, dfilter *sfcode)
     count = 0;
     fdata = start_fd;
 
     count = 0;
     fdata = start_fd;
 
-    /* Update the progress bar when it gets to this value. */
-    progbar_nextstep = 0;
+    cf->progbar_nextstep = 0;
     /* When we reach the value that triggers a progress bar update,
        bump that value by this amount. */
     /* When we reach the value that triggers a progress bar update,
        bump that value by this amount. */
-    progbar_quantum = cf->count/N_PROGBAR_UPDATES;
+    cf->progbar_quantum = cf->count/N_PROGBAR_UPDATES;
 
     stop_flag = FALSE;
 
     stop_flag = FALSE;
-    progbar = create_progress_dlg("Searching", "Cancel", &stop_flag);
+    g_get_current_time(&start_time);
 
     fdata = start_fd;
     for (;;) {
 
     fdata = start_fd;
     for (;;) {
@@ -1413,15 +1477,26 @@ find_packet(capture_file *cf, dfilter *sfcode)
          to repaint what's pending, and doing so may involve an "ioctl()"
          to see if there's any pending input from an X server, and doing
          that for every packet can be costly, especially on a big file. */
          to repaint what's pending, and doing so may involve an "ioctl()"
          to see if there's any pending input from an X server, and doing
          that for every packet can be costly, especially on a big file. */
-      if (count >= progbar_nextstep) {
+      if (count >= cf->progbar_nextstep) {
         /* let's not divide by zero. I should never be started
          * with count == 0, so let's assert that
          */
         g_assert(cf->count > 0);
 
         /* let's not divide by zero. I should never be started
          * with count == 0, so let's assert that
          */
         g_assert(cf->count > 0);
 
-        update_progress_dlg(progbar, (gfloat) count / cf->count);
+        prog_val = (gfloat) count / cf->count;
+
+        /* Create the progress bar if necessary */
+        if (progbar == NULL)
+           progbar = delayed_create_progress_dlg("Searching", cf->sfilter, "Cancel",
+             &stop_flag, &start_time, prog_val);
+        
+        if (progbar != NULL) {
+          g_snprintf(status_str, sizeof(status_str),
+                     "%4u of %u frames", count, cf->count);
+          update_progress_dlg(progbar, prog_val, status_str);
+        }
 
 
-        progbar_nextstep += progbar_quantum;
+        cf->progbar_nextstep += cf->progbar_quantum;
       }
 
       if (stop_flag) {
       }
 
       if (stop_flag) {
@@ -1449,13 +1524,14 @@ find_packet(capture_file *cf, dfilter *sfcode)
       /* Is this packet in the display? */
       if (fdata->flags.passed_dfilter) {
         /* Yes.  Does it match the search filter? */
       /* Is this packet in the display? */
       if (fdata->flags.passed_dfilter) {
         /* Yes.  Does it match the search filter? */
-        protocol_tree = proto_tree_create_root();
+        /* XXX - do something with "err" */
         wtap_seek_read(cf->wth, fdata->file_off, &cf->pseudo_header,
         wtap_seek_read(cf->wth, fdata->file_off, &cf->pseudo_header,
-                       cf->pd, fdata->cap_len);
-        edt = epan_dissect_new(&cf->pseudo_header, cf->pd, fdata, protocol_tree);
-        frame_matched = dfilter_apply(sfcode, protocol_tree, cf->pd, fdata->cap_len);
-        proto_tree_free(protocol_tree);
-       epan_dissect_free(edt);
+                       cf->pd, fdata->cap_len, &err);
+        edt = epan_dissect_new(TRUE, FALSE);
+        epan_dissect_prime_dfilter(edt, sfcode);
+        epan_dissect_run(edt, &cf->pseudo_header, cf->pd, fdata, NULL);
+        frame_matched = dfilter_apply_edt(sfcode, edt);
+        epan_dissect_free(edt);
         if (frame_matched) {
           new_fd = fdata;
           break;       /* found it! */
         if (frame_matched) {
           new_fd = fdata;
           break;       /* found it! */
@@ -1469,8 +1545,10 @@ find_packet(capture_file *cf, dfilter *sfcode)
       }
     }
 
       }
     }
 
-    /* We're done scanning the packets; destroy the progress bar. */
-    destroy_progress_dlg(progbar);
+    /* We're done scanning the packets; destroy the progress bar if it
+       was created. */
+    if (progbar != NULL)
+      destroy_progress_dlg(progbar);
   }
 
   if (new_fd != NULL) {
   }
 
   if (new_fd != NULL) {
@@ -1514,6 +1592,7 @@ void
 select_packet(capture_file *cf, int row)
 {
   frame_data *fdata;
 select_packet(capture_file *cf, int row)
 {
   frame_data *fdata;
+  int err;
 
   /* Get the frame data struct pointer for this frame */
   fdata = (frame_data *) gtk_clist_get_row_data(GTK_CLIST(packet_list), row);
 
   /* Get the frame data struct pointer for this frame */
   fdata = (frame_data *) gtk_clist_get_row_data(GTK_CLIST(packet_list), row);
@@ -1553,22 +1632,25 @@ select_packet(capture_file *cf, int row)
   cf->current_frame = fdata;
 
   /* Get the data in that frame. */
   cf->current_frame = fdata;
 
   /* Get the data in that frame. */
+  /* XXX - do something with "err" */
   wtap_seek_read (cf->wth, fdata->file_off, &cf->pseudo_header,
   wtap_seek_read (cf->wth, fdata->file_off, &cf->pseudo_header,
-                       cf->pd, fdata->cap_len);
+                       cf->pd, fdata->cap_len, &err);
 
   /* Create the logical protocol tree. */
 
   /* Create the logical protocol tree. */
-  if (cf->protocol_tree)
-      proto_tree_free(cf->protocol_tree);
-  cf->protocol_tree = proto_tree_create_root();
-  proto_tree_is_visible = TRUE;
-  cf->edt = epan_dissect_new(&cf->pseudo_header, cf->pd, cf->current_frame,
-               cf->protocol_tree);
-  proto_tree_is_visible = FALSE;
-
-  /* Display the GUI protocol tree and hex dump. */
-  clear_tree_and_hex_views();
-  proto_tree_draw(cf->protocol_tree, tree_view);
-  packet_hex_print(GTK_TEXT(byte_view), cf->pd, cf->current_frame, NULL);
+  if (cf->edt != NULL) {
+    epan_dissect_free(cf->edt);
+    cf->edt = NULL;
+  }
+  /* We don't need the columns here. */
+  cf->edt = epan_dissect_new(TRUE, TRUE);
+  epan_dissect_run(cf->edt, &cf->pseudo_header, cf->pd, cf->current_frame,
+          NULL);
+
+  /* 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_byte_views(cf->edt, tree_view, byte_nb_ptr);
+  proto_tree_draw(cf->edt->tree, tree_view);
 
   /* A packet is selected. */
   set_menus_for_selected_packet(TRUE);
 
   /* A packet is selected. */
   set_menus_for_selected_packet(TRUE);
@@ -1578,20 +1660,20 @@ select_packet(capture_file *cf, int row)
 void
 unselect_packet(capture_file *cf)
 {
 void
 unselect_packet(capture_file *cf)
 {
-  /* Destroy the protocol tree for that packet. */
-  if (cf->protocol_tree != NULL) {
-    proto_tree_free(cf->protocol_tree);
-    cf->protocol_tree = NULL;
+  /* Destroy the epan_dissect_t for the unselected packet. */
+  if (cf->edt != NULL) {
     epan_dissect_free(cf->edt);
     epan_dissect_free(cf->edt);
+    cf->edt = NULL;
   }
 
   }
 
-  finfo_selected = NULL;
-
   /* Clear out the display of that packet. */
   clear_tree_and_hex_views();
 
   /* No packet is selected. */
   set_menus_for_selected_packet(FALSE);
   /* Clear out the display of that packet. */
   clear_tree_and_hex_views();
 
   /* No packet is selected. */
   set_menus_for_selected_packet(FALSE);
+
+  /* No protocol tree means no selected field. */
+  unselect_field();
 }
 
 /* Set the selected row and the focus row of the packet list to the specified
 }
 
 /* Set the selected row and the focus row of the packet list to the specified
@@ -1615,6 +1697,35 @@ set_selected_row(int row)
   gtk_clist_select_row(GTK_CLIST(packet_list), row, -1);
 }
 
   gtk_clist_select_row(GTK_CLIST(packet_list), row, -1);
 }
 
+/* Unset the selected protocol tree field, if any. */
+void
+unselect_field(void)
+{
+  statusbar_pop_field_msg();
+  finfo_selected = NULL;
+  set_menus_for_selected_tree_row(FALSE);
+}
+
+/*
+ * Mark a particular frame.
+ */
+void
+mark_frame(capture_file *cf, frame_data *frame)
+{
+  frame->flags.marked = TRUE;
+  cf->marked_count++;
+}
+
+/*
+ * Unmark a particular frame.
+ */
+void
+unmark_frame(capture_file *cf, frame_data *frame)
+{
+  frame->flags.marked = FALSE;
+  cf->marked_count--;
+}
+
 static void
 freeze_clist(capture_file *cf)
 {
 static void
 freeze_clist(capture_file *cf)
 {
@@ -1653,9 +1764,16 @@ thaw_clist(capture_file *cf)
     gtk_clist_set_column_resizeable(GTK_CLIST(packet_list), i, TRUE);
 }
 
     gtk_clist_set_column_resizeable(GTK_CLIST(packet_list), i, TRUE);
 }
 
-int
-save_cap_file(char *fname, capture_file *cf, gboolean save_filtered, gboolean save_marked,
-               guint save_format)
+/*
+ * Save a capture to a file, in a particular format, saving either
+ * all packets, all currently-displayed packets, or all marked packets.
+ *
+ * Returns TRUE if it succeeds, FALSE otherwise; if it fails, it pops
+ * up a message box for the failure.
+ */
+gboolean
+save_cap_file(char *fname, capture_file *cf, gboolean save_filtered,
+               gboolean save_marked, guint save_format)
 {
   gchar        *from_filename;
   gchar        *name_ptr, *save_msg, *save_fmt = " Saving: %s...";
 {
   gchar        *from_filename;
   gchar        *name_ptr, *save_msg, *save_fmt = " Saving: %s...";
@@ -1667,21 +1785,37 @@ save_cap_file(char *fname, capture_file *cf, gboolean save_filtered, gboolean sa
   struct wtap_pkthdr hdr;
   union wtap_pseudo_header pseudo_header;
   guint8        pd[65536];
   struct wtap_pkthdr hdr;
   union wtap_pseudo_header pseudo_header;
   guint8        pd[65536];
+  struct stat   infile, outfile;
 
   name_ptr = get_basename(fname);
   msg_len = strlen(name_ptr) + strlen(save_fmt) + 2;
   save_msg = g_malloc(msg_len);
   snprintf(save_msg, msg_len, save_fmt, name_ptr);
 
   name_ptr = get_basename(fname);
   msg_len = strlen(name_ptr) + strlen(save_fmt) + 2;
   save_msg = g_malloc(msg_len);
   snprintf(save_msg, msg_len, save_fmt, name_ptr);
-  gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx, save_msg);
+  statusbar_push_file_msg(save_msg);
   g_free(save_msg);
 
   g_free(save_msg);
 
+  /* 
+   * Check that the from file is not the same as to file 
+   * We do it here so we catch all cases ...
+   * Unfortunately, the file requester gives us an absolute file
+   * name and the read file name may be relative (if supplied on
+   * the command line). From Joerg Mayer.
+   */
+   infile.st_ino = 1;   /* These prevent us from getting equality         */
+   outfile.st_ino = 2;  /* If one or other of the files is not accessible */
+   stat(cf->filename, &infile);
+   stat(fname, &outfile);
+   if (infile.st_ino == outfile.st_ino) {
+    simple_dialog(ESD_TYPE_CRIT, NULL, 
+                     "Can't save over current capture file: %s!",
+                     cf->filename);
+    goto fail;
+  }
+
   if (!save_filtered && !save_marked && save_format == cf->cd_t) {
     /* We're not filtering packets, and we're saving it in the format
        it's already in, so we can just move or copy the raw data. */
 
   if (!save_filtered && !save_marked && save_format == cf->cd_t) {
     /* We're not filtering packets, and we're saving it in the format
        it's already in, so we can just move or copy the raw data. */
 
-    /* In this branch, we set "err" only if we get an error, so we
-       must first clear it. */
-    err = 0;
     if (cf->is_tempfile) {
       /* The file being saved is a temporary file from a live
          capture, so it doesn't need to stay around under that name;
     if (cf->is_tempfile) {
       /* The file being saved is a temporary file from a live
          capture, so it doesn't need to stay around under that name;
@@ -1705,10 +1839,9 @@ save_cap_file(char *fname, capture_file *cf, gboolean save_filtered, gboolean sa
             be if we didn't have permission to remove the file from
             the temporary directory, and that might be fixable - but
             is it worth requiring the user to go off and fix it?) */
             be if we didn't have permission to remove the file from
             the temporary directory, and that might be fixable - but
             is it worth requiring the user to go off and fix it?) */
-         err = errno;
          simple_dialog(ESD_TYPE_CRIT, NULL,
          simple_dialog(ESD_TYPE_CRIT, NULL,
-                               file_rename_error_message(err), fname);
-         goto done;
+                               file_rename_error_message(errno), fname);
+         goto fail;
        }
       }
 #else
        }
       }
 #else
@@ -1721,11 +1854,11 @@ save_cap_file(char *fname, capture_file *cf, gboolean save_filtered, gboolean sa
       do_copy = TRUE;
       from_filename = cf->filename;
     }
       do_copy = TRUE;
       from_filename = cf->filename;
     }
-    /* Copy the file, if we haven't moved it. */
+
     if (do_copy) {
     if (do_copy) {
-           if (!copy_binary_file(from_filename, fname)) {
-               goto done;
-           }
+      /* Copy the file, if we haven't moved it. */
+      if (!copy_binary_file(from_filename, fname))
+       goto fail;
     }
   } else {
     /* Either we're filtering packets, or we're saving in a different
     }
   } else {
     /* Either we're filtering packets, or we're saving in a different
@@ -1734,8 +1867,8 @@ save_cap_file(char *fname, capture_file *cf, gboolean save_filtered, gboolean sa
     pdh = wtap_dump_open(fname, save_format, cf->lnk_t, cf->snap, &err);
     if (pdh == NULL) {
       simple_dialog(ESD_TYPE_CRIT, NULL,
     pdh = wtap_dump_open(fname, save_format, cf->lnk_t, cf->snap, &err);
     if (pdh == NULL) {
       simple_dialog(ESD_TYPE_CRIT, NULL,
-                       file_open_error_message(err, TRUE), fname);
-      goto done;
+                       file_open_error_message(err, TRUE, save_format), fname);
+      goto fail;
     }
 
     /* XXX - have a way to save only the packets currently selected by
     }
 
     /* XXX - have a way to save only the packets currently selected by
@@ -1762,14 +1895,19 @@ save_cap_file(char *fname, capture_file *cf, gboolean save_filtered, gboolean sa
         hdr.caplen = fdata->cap_len;
         hdr.len = fdata->pkt_len;
         hdr.pkt_encap = fdata->lnk_t;
         hdr.caplen = fdata->cap_len;
         hdr.len = fdata->pkt_len;
         hdr.pkt_encap = fdata->lnk_t;
-       wtap_seek_read(cf->wth, fdata->file_off, &pseudo_header,
-               pd, fdata->cap_len);
+       if (!wtap_seek_read(cf->wth, fdata->file_off, &pseudo_header,
+               pd, fdata->cap_len, &err)) {
+         simple_dialog(ESD_TYPE_CRIT, NULL,
+                               file_read_error_message(err), cf->filename);
+         wtap_dump_close(pdh, &err);
+          goto fail;
+       }
 
         if (!wtap_dump(pdh, &hdr, &pseudo_header, pd, &err)) {
 
         if (!wtap_dump(pdh, &hdr, &pseudo_header, pd, &err)) {
-           simple_dialog(ESD_TYPE_CRIT, NULL,
+         simple_dialog(ESD_TYPE_CRIT, NULL,
                                file_write_error_message(err), fname);
                                file_write_error_message(err), fname);
-           wtap_dump_close(pdh, &err);
-           goto done;
+         wtap_dump_close(pdh, &err);
+          goto fail;
        }
       }
     }
        }
       }
     }
@@ -1777,55 +1915,57 @@ save_cap_file(char *fname, capture_file *cf, gboolean save_filtered, gboolean sa
     if (!wtap_dump_close(pdh, &err)) {
       simple_dialog(ESD_TYPE_WARN, NULL,
                file_close_error_message(err), fname);
     if (!wtap_dump_close(pdh, &err)) {
       simple_dialog(ESD_TYPE_WARN, NULL,
                file_close_error_message(err), fname);
-      goto done;
+      goto fail;
     }
   }
 
     }
   }
 
-done:
-
   /* Pop the "Saving:" message off the status bar. */
   /* Pop the "Saving:" message off the status bar. */
-  gtk_statusbar_pop(GTK_STATUSBAR(info_bar), file_ctx);
-  if (err == 0) {
-    if (!save_filtered && !save_marked) {
-      /* We saved the entire capture, not just some packets from it.
-         Open and read the file we saved it to.
-
-        XXX - this is somewhat of a waste; we already have the
-        packets, all this gets us is updated file type information
-        (which we could just stuff into "cf"), and having the new
-        file be the one we have opened and from which we're reading
-        the data, and it means we have to spend time opening and
-        reading the file, which could be a significant amount of
-        time if the file is large. */
-      cf->user_saved = TRUE;
-
-      if ((err = open_cap_file(fname, FALSE, cf)) == 0) {
-       /* XXX - report errors if this fails? */
-       switch (read_cap_file(cf, &err)) {
-
-       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;
-
-       case READ_ABORTED:
-         /* The user bailed out of re-reading the capture file; the
-            capture file has been closed - just return (without
-            changing any menu settings; "close_cap_file()" set them
-            correctly for the "no capture file open" state). */
-         return 0;
-       }
-       set_menus_for_unsaved_capture_file(FALSE);
+  statusbar_pop_file_msg();
+  if (!save_filtered && !save_marked) {
+    /* We saved the entire capture, not just some packets from it.
+       Open and read the file we saved it to.
+
+       XXX - this is somewhat of a waste; we already have the
+       packets, all this gets us is updated file type information
+       (which we could just stuff into "cf"), and having the new
+       file be the one we have opened and from which we're reading
+       the data, and it means we have to spend time opening and
+       reading the file, which could be a significant amount of
+       time if the file is large. */
+    cf->user_saved = TRUE;
+
+    if ((err = open_cap_file(fname, FALSE, cf)) == 0) {
+      /* XXX - report errors if this fails?
+         What should we return if it fails or is aborted? */
+      switch (read_cap_file(cf, &err)) {
+
+      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;
+
+      case READ_ABORTED:
+       /* The user bailed out of re-reading the capture file; the
+          capture file has been closed - just return (without
+          changing any menu settings; "close_cap_file()" set them
+          correctly for the "no capture file open" state). */
+       break;
       }
       }
+      set_menus_for_unsaved_capture_file(FALSE);
     }
   }
     }
   }
-  return err;
+  return TRUE;
+
+fail:
+  /* Pop the "Saving:" message off the status bar. */
+  statusbar_pop_file_msg();
+  return FALSE;
 }
 
 char *
 }
 
 char *
-file_open_error_message(int err, gboolean for_writing)
+file_open_error_message(int err, gboolean for_writing, int file_type)
 {
   char *errmsg;
   static char errmsg_errno[1024+1];
 {
   char *errmsg;
   static char errmsg_errno[1024+1];
@@ -1836,12 +1976,25 @@ file_open_error_message(int err, gboolean for_writing)
     errmsg = "The file \"%s\" is a \"special file\" or socket or other non-regular file.";
     break;
 
     errmsg = "The file \"%s\" is a \"special file\" or socket or other non-regular file.";
     break;
 
+  case WTAP_ERR_RANDOM_OPEN_PIPE:
+    /* Seen only when opening a capture file for reading. */
+    errmsg = "The file \"%s\" is a pipe or FIFO; Ethereal cannot read pipe or FIFO files.";
+    break;
+
   case WTAP_ERR_FILE_UNKNOWN_FORMAT:
   case WTAP_ERR_UNSUPPORTED:
     /* Seen only when opening a capture file for reading. */
     errmsg = "The file \"%s\" is not a capture file in a format Ethereal understands.";
     break;
 
   case WTAP_ERR_FILE_UNKNOWN_FORMAT:
   case WTAP_ERR_UNSUPPORTED:
     /* Seen only when opening a capture file for reading. */
     errmsg = "The file \"%s\" is not a capture file in a format Ethereal understands.";
     break;
 
+  case WTAP_ERR_CANT_WRITE_TO_PIPE:
+    /* Seen only when opening a capture file for writing. */
+    snprintf(errmsg_errno, sizeof(errmsg_errno),
+            "The file \"%%s\" is a pipe, and %s capture files cannot be "
+            "written to a pipe.", wtap_file_type_string(file_type));
+    errmsg = errmsg_errno;
+    break;
+
   case WTAP_ERR_UNSUPPORTED_FILE_TYPE:
     /* Seen only when opening a capture file for writing. */
     errmsg = "Ethereal does not support writing capture files in that format.";
   case WTAP_ERR_UNSUPPORTED_FILE_TYPE:
     /* Seen only when opening a capture file for writing. */
     errmsg = "Ethereal does not support writing capture files in that format.";
@@ -1868,7 +2021,7 @@ file_open_error_message(int err, gboolean for_writing)
 
   case WTAP_ERR_SHORT_READ:
     errmsg = "The file \"%s\" appears to have been cut short"
 
   case WTAP_ERR_SHORT_READ:
     errmsg = "The file \"%s\" appears to have been cut short"
-             " in the middle of a packet.";
+             " in the middle of a packet or other data.";
     break;
 
   case WTAP_ERR_SHORT_WRITE:
     break;
 
   case WTAP_ERR_SHORT_WRITE:
@@ -1895,7 +2048,8 @@ file_open_error_message(int err, gboolean for_writing)
 
   default:
     snprintf(errmsg_errno, sizeof(errmsg_errno),
 
   default:
     snprintf(errmsg_errno, sizeof(errmsg_errno),
-                   "The file \"%%s\" could not be opened: %s.",
+                   "The file \"%%s\" could not be %s: %s.",
+                               for_writing ? "created" : "opened",
                                wtap_strerror(err));
     errmsg = errmsg_errno;
     break;
                                wtap_strerror(err));
     errmsg = errmsg_errno;
     break;
@@ -1985,7 +2139,7 @@ file_close_error_message(int err)
     break;
 
   case WTAP_ERR_SHORT_WRITE:
     break;
 
   case WTAP_ERR_SHORT_WRITE:
-    errmsg = "Not all the data could be written to the file \"%s\".";
+    errmsg = "Not all the packets could be written to the file \"%s\".";
     break;
 
   case ENOSPC:
     break;
 
   case ENOSPC:
@@ -2026,7 +2180,7 @@ copy_binary_file(char *from_filename, char *to_filename)
       if (from_fd < 0) {
        err = errno;
        simple_dialog(ESD_TYPE_CRIT, NULL,
       if (from_fd < 0) {
        err = errno;
        simple_dialog(ESD_TYPE_CRIT, NULL,
-                       file_open_error_message(err, TRUE), from_filename);
+                       file_open_error_message(err, TRUE, 0), from_filename);
        goto done;
       }
 
        goto done;
       }
 
@@ -2039,7 +2193,7 @@ copy_binary_file(char *from_filename, char *to_filename)
       if (to_fd < 0) {
        err = errno;
        simple_dialog(ESD_TYPE_CRIT, NULL,
       if (to_fd < 0) {
        err = errno;
        simple_dialog(ESD_TYPE_CRIT, NULL,
-                       file_open_error_message(err, TRUE), to_filename);
+                       file_open_error_message(err, TRUE, 0), to_filename);
        close(from_fd);
        goto done;
       }
        close(from_fd);
        goto done;
       }