The Styleguide section has been moved to the Wireshark Developer's Guide.
[obnox/wireshark/wip.git] / file.c
diff --git a/file.c b/file.c
index 21e3554df35a21b0f28c713d1ccf73d339db27c6..c69e0ea51877738d14db5580992c228454b6d727 100644 (file)
--- a/file.c
+++ b/file.c
@@ -60,6 +60,7 @@
 #include "merge.h"
 #include "alert_box.h"
 #include "simple_dialog.h"
+#include "main_statusbar.h"
 #include "progress_dlg.h"
 #include "ui_util.h"
 #include <epan/prefs.h>
 #include <wsutil/file_util.h>
 #include <epan/strutil.h>
 
-
 #ifdef HAVE_LIBPCAP
 gboolean auto_scroll_live;
 #endif
 
+static guint32 cum_bytes;
 static nstime_t first_ts;
 static nstime_t prev_dis_ts;
-static guint32 cum_bytes = 0;
+static nstime_t prev_cap_ts;
+
+static gulong computed_elapsed;
 
 static void cf_reset_state(capture_file *cf);
 
@@ -88,46 +91,60 @@ static int read_packet(capture_file *cf, dfilter_t *dfcode,
     gboolean filtering_tap_listeners, guint tap_flags, gint64 offset);
 
 static void rescan_packets(capture_file *cf, const char *action, const char *action_item,
-       gboolean refilter, gboolean redissect);
+    gboolean refilter, gboolean redissect);
 
-static gboolean match_protocol_tree(capture_file *cf, frame_data *fdata,
-       void *criterion);
+typedef enum {
+  MR_NOTMATCHED,
+  MR_MATCHED,
+  MR_ERROR
+} match_result;
+static match_result match_protocol_tree(capture_file *cf, frame_data *fdata,
+    void *criterion);
 static void match_subtree_text(proto_node *node, gpointer data);
-static gboolean match_summary_line(capture_file *cf, frame_data *fdata,
-       void *criterion);
-static gboolean match_ascii_and_unicode(capture_file *cf, frame_data *fdata,
-       void *criterion);
-static gboolean match_ascii(capture_file *cf, frame_data *fdata,
-       void *criterion);
-static gboolean match_unicode(capture_file *cf, frame_data *fdata,
-       void *criterion);
-static gboolean match_binary(capture_file *cf, frame_data *fdata,
-       void *criterion);
-static gboolean match_dfilter(capture_file *cf, frame_data *fdata,
-       void *criterion);
+static match_result match_summary_line(capture_file *cf, frame_data *fdata,
+    void *criterion);
+static match_result match_ascii_and_unicode(capture_file *cf, frame_data *fdata,
+    void *criterion);
+static match_result match_ascii(capture_file *cf, frame_data *fdata,
+    void *criterion);
+static match_result match_unicode(capture_file *cf, frame_data *fdata,
+    void *criterion);
+static match_result match_binary(capture_file *cf, frame_data *fdata,
+    void *criterion);
+static match_result match_dfilter(capture_file *cf, frame_data *fdata,
+    void *criterion);
+static match_result match_marked(capture_file *cf, frame_data *fdata,
+    void *criterion);
+static match_result match_time_reference(capture_file *cf, frame_data *fdata,
+    void *criterion);
 static gboolean find_packet(capture_file *cf,
-       gboolean (*match_function)(capture_file *, frame_data *, void *),
-       void *criterion);
+    match_result (*match_function)(capture_file *, frame_data *, void *),
+    void *criterion, search_direction dir);
 
 static void cf_open_failure_alert_box(const char *filename, int err,
-                                     gchar *err_info, gboolean for_writing,
-                                     int file_type);
+                      gchar *err_info, gboolean for_writing,
+                      int file_type);
 static const char *file_rename_error_message(int err);
 static void cf_write_failure_alert_box(const char *filename, int err);
 static void cf_close_failure_alert_box(const char *filename, int err);
-
+#ifdef NEW_PACKET_LIST
+static void ref_time_packets(capture_file *cf);
+#endif
 /* Update the progress bar this many times when reading a file. */
-#define N_PROGBAR_UPDATES      100
+#define N_PROGBAR_UPDATES   100
+/* We read around 200k/100ms don't update the progress bar more often than that */
+#define MIN_QUANTUM         200000
+#define MIN_NUMBER_OF_PACKET 1500
 
 /* Number of "frame_data" structures per memory chunk.
    XXX - is this the right number? */
-#define        FRAME_DATA_CHUNK_SIZE   1024
+#define FRAME_DATA_CHUNK_SIZE   1024
 
 
 /* this callback mechanism should possibly be replaced by the g_signal_...() stuff (if I only would know how :-) */
 typedef struct {
-    cf_callback_t cb_fct;
-    gpointer user_data;
+  cf_callback_t cb_fct;
+  gpointer user_data;
 } cf_callback_data_t;
 
 static GList *cf_callbacks = NULL;
@@ -135,96 +152,131 @@ static GList *cf_callbacks = NULL;
 static void
 cf_callback_invoke(int event, gpointer data)
 {
-    cf_callback_data_t *cb;
-    GList *cb_item = cf_callbacks;
+  cf_callback_data_t *cb;
+  GList *cb_item = cf_callbacks;
 
-    /* there should be at least one interested */
-    g_assert(cb_item != NULL);
+  /* there should be at least one interested */
+  g_assert(cb_item != NULL);
 
-    while(cb_item != NULL) {
-        cb = cb_item->data;
-        cb->cb_fct(event, data, cb->user_data);
-        cb_item = g_list_next(cb_item);
-    }
+  while(cb_item != NULL) {
+    cb = cb_item->data;
+    cb->cb_fct(event, data, cb->user_data);
+    cb_item = g_list_next(cb_item);
+  }
 }
 
 
 void
 cf_callback_add(cf_callback_t func, gpointer user_data)
 {
-    cf_callback_data_t *cb;
+  cf_callback_data_t *cb;
 
-    cb = g_malloc(sizeof(cf_callback_data_t));
-    cb->cb_fct = func;
-    cb->user_data = user_data;
+  cb = g_malloc(sizeof(cf_callback_data_t));
+  cb->cb_fct = func;
+  cb->user_data = user_data;
 
-    cf_callbacks = g_list_append(cf_callbacks, cb);
+  cf_callbacks = g_list_append(cf_callbacks, cb);
 }
 
 void
 cf_callback_remove(cf_callback_t func)
 {
-    cf_callback_data_t *cb;
-    GList *cb_item = cf_callbacks;
-
-    while(cb_item != NULL) {
-        cb = cb_item->data;
-        if(cb->cb_fct == func) {
-            cf_callbacks = g_list_remove(cf_callbacks, cb);
-            g_free(cb);
-            return;
-        }
-        cb_item = g_list_next(cb_item);
+  cf_callback_data_t *cb;
+  GList *cb_item = cf_callbacks;
+
+  while(cb_item != NULL) {
+    cb = cb_item->data;
+    if(cb->cb_fct == func) {
+      cf_callbacks = g_list_remove(cf_callbacks, cb);
+      g_free(cb);
+      return;
     }
+    cb_item = g_list_next(cb_item);
+  }
 
-    g_assert_not_reached();
+  g_assert_not_reached();
 }
 
 void
 cf_timestamp_auto_precision(capture_file *cf)
 {
-       int prec = timestamp_get_precision();
-
-
-       /* don't try to get the file's precision if none is opened */
-       if(cf->state == FILE_CLOSED) {
-               return;
-       }
-
-       /* if we are in auto mode, set precision of current file */
-       if(prec == TS_PREC_AUTO ||
-         prec == TS_PREC_AUTO_SEC ||
-         prec == TS_PREC_AUTO_DSEC ||
-         prec == TS_PREC_AUTO_CSEC ||
-         prec == TS_PREC_AUTO_MSEC ||
-         prec == TS_PREC_AUTO_USEC ||
-         prec == TS_PREC_AUTO_NSEC)
-       {
-               switch(wtap_file_tsprecision(cf->wth)) {
-               case(WTAP_FILE_TSPREC_SEC):
-                       timestamp_set_precision(TS_PREC_AUTO_SEC);
-                       break;
-               case(WTAP_FILE_TSPREC_DSEC):
-                       timestamp_set_precision(TS_PREC_AUTO_DSEC);
-                       break;
-               case(WTAP_FILE_TSPREC_CSEC):
-                       timestamp_set_precision(TS_PREC_AUTO_CSEC);
-                       break;
-               case(WTAP_FILE_TSPREC_MSEC):
-                       timestamp_set_precision(TS_PREC_AUTO_MSEC);
-                       break;
-               case(WTAP_FILE_TSPREC_USEC):
-                       timestamp_set_precision(TS_PREC_AUTO_USEC);
-                       break;
-               case(WTAP_FILE_TSPREC_NSEC):
-                       timestamp_set_precision(TS_PREC_AUTO_NSEC);
-                       break;
-               default:
-                       g_assert_not_reached();
-               }
-       }
+#ifdef NEW_PACKET_LIST
+  int i;
+#endif
+  int prec = timestamp_get_precision();
+
+
+  /* don't try to get the file's precision if none is opened */
+  if(cf->state == FILE_CLOSED) {
+    return;
+  }
+
+  /* if we are in auto mode, set precision of current file */
+  if(prec == TS_PREC_AUTO ||
+     prec == TS_PREC_AUTO_SEC ||
+     prec == TS_PREC_AUTO_DSEC ||
+     prec == TS_PREC_AUTO_CSEC ||
+     prec == TS_PREC_AUTO_MSEC ||
+     prec == TS_PREC_AUTO_USEC ||
+     prec == TS_PREC_AUTO_NSEC)
+  {
+    switch(wtap_file_tsprecision(cf->wth)) {
+    case(WTAP_FILE_TSPREC_SEC):
+      timestamp_set_precision(TS_PREC_AUTO_SEC);
+      break;
+    case(WTAP_FILE_TSPREC_DSEC):
+      timestamp_set_precision(TS_PREC_AUTO_DSEC);
+      break;
+    case(WTAP_FILE_TSPREC_CSEC):
+      timestamp_set_precision(TS_PREC_AUTO_CSEC);
+      break;
+    case(WTAP_FILE_TSPREC_MSEC):
+      timestamp_set_precision(TS_PREC_AUTO_MSEC);
+      break;
+    case(WTAP_FILE_TSPREC_USEC):
+      timestamp_set_precision(TS_PREC_AUTO_USEC);
+      break;
+    case(WTAP_FILE_TSPREC_NSEC):
+      timestamp_set_precision(TS_PREC_AUTO_NSEC);
+      break;
+    default:
+      g_assert_not_reached();
+    }
+  }
+#ifdef NEW_PACKET_LIST
+  /* Set the column widths of those columns that show the time in
+     "command-line-specified" format. */
+  for (i = 0; i < cf->cinfo.num_cols; i++) {
+    if (col_has_time_fmt(&cf->cinfo, i)) {
+      new_packet_list_resize_column(i);
+    }
+  }
+#endif
+}
+
+gulong
+cf_get_computed_elapsed(void)
+{
+  return computed_elapsed;
 }
 
+static void reset_elapsed(void)
+{
+  computed_elapsed = 0;
+}
+
+static void compute_elapsed(GTimeVal *start_time)
+{
+  gdouble    delta_time;
+  GTimeVal   time_now;
+
+  g_get_current_time(&time_now);
+
+  delta_time = (time_now.tv_sec - start_time->tv_sec) * 1e6 +
+    time_now.tv_usec - start_time->tv_usec;
+
+  computed_elapsed = (gulong) (delta_time / 1000); /* ms*/
+}
 
 cf_status_t
 cf_open(capture_file *cf, const char *fname, gboolean is_tempfile, int *err)
@@ -240,6 +292,8 @@ cf_open(capture_file *cf, const char *fname, gboolean is_tempfile, int *err)
      and fill in the information for this file. */
   cf_reset_state(cf);
 
+  /* Cleanup all data structures used for dissection. */
+  cleanup_dissection();
   /* Initialize all data structures used for dissection. */
   init_dissection();
 
@@ -260,10 +314,14 @@ cf_open(capture_file *cf, const char *fname, gboolean is_tempfile, int *err)
   /* If it's a temporary capture buffer file, mark it as not saved. */
   cf->user_saved = !is_tempfile;
 
+  reset_elapsed();
+
   cf->cd_t        = wtap_file_type(cf->wth);
   cf->count     = 0;
   cf->displayed_count = 0;
   cf->marked_count = 0;
+  cf->ignored_count = 0;
+  cf->ref_time_count = 0;
   cf->drops_known = FALSE;
   cf->drops     = 0;
   cf->snap      = wtap_snapshot_length(cf->wth);
@@ -273,24 +331,34 @@ cf_open(capture_file *cf, const char *fname, gboolean is_tempfile, int *err)
     cf->snap = WTAP_MAX_PACKET_SIZE;
   } else
     cf->has_snap = TRUE;
+
   nstime_set_zero(&cf->elapsed_time);
   nstime_set_unset(&first_ts);
   nstime_set_unset(&prev_dis_ts);
+  nstime_set_unset(&prev_cap_ts);
+  cum_bytes = 0;
 
 #if GLIB_CHECK_VERSION(2,10,0)
 #else
-  /* memory chunks have been deprecated in favor of the slice allocator, 
+  /* memory chunks have been deprecated in favor of the slice allocator,
    * which has been added in 2.10
    */
   cf->plist_chunk = g_mem_chunk_new("frame_data_chunk",
-       sizeof(frame_data),
-       FRAME_DATA_CHUNK_SIZE * sizeof(frame_data),
-       G_ALLOC_AND_FREE);
+    sizeof(frame_data),
+    FRAME_DATA_CHUNK_SIZE * sizeof(frame_data),
+    G_ALLOC_AND_FREE);
   g_assert(cf->plist_chunk);
 #endif
+
+#ifdef NEW_PACKET_LIST
+  /* Adjust timestamp precision if auto is selected, col width will be adjusted */
+  cf_timestamp_auto_precision(cf);
+  /* XXX needed ? */
+  new_packet_list_queue_draw();
+#else
   /* change the time formats now, as we might have a new precision */
   cf_change_time_formats(cf);
-
+#endif
   fileset_file_opened(fname);
 
   if(cf->cd_t == WTAP_FILE_BER) {
@@ -335,8 +403,10 @@ cf_reset_state(capture_file *cf)
   cf->user_saved = FALSE;
 
 #if GLIB_CHECK_VERSION(2,10,0)
+  if (cf->plist_start != NULL)
+    g_slice_free_chain(frame_data, cf->plist_start, next);
 #else
-  /* memory chunks have been deprecated in favor of the slice allocator, 
+  /* memory chunks have been deprecated in favor of the slice allocator,
    * which has been added in 2.10
    */
   if (cf->plist_chunk != NULL) {
@@ -344,13 +414,11 @@ cf_reset_state(capture_file *cf)
     cf->plist_chunk = NULL;
   }
 #endif
-  if (cf->rfcode != NULL) {
-    dfilter_free(cf->rfcode);
-    cf->rfcode = NULL;
-  }
-  cf->plist = NULL;
+  dfilter_free(cf->rfcode);
+  cf->rfcode = NULL;
+  cf->plist_start = NULL;
   cf->plist_end = NULL;
-  cf_unselect_packet(cf);      /* nothing to select */
+  cf_unselect_packet(cf);   /* nothing to select */
   cf->first_displayed = NULL;
   cf->last_displayed = NULL;
 
@@ -362,6 +430,7 @@ cf_reset_state(capture_file *cf)
   /* Clear the packet list. */
 #ifdef NEW_PACKET_LIST
   new_packet_list_freeze();
+  new_packet_list_clear();
   new_packet_list_thaw();
 #else
   packet_list_freeze();
@@ -400,13 +469,56 @@ cf_close(capture_file *cf)
 }
 
 /* an out of memory exception occured, wait for a user button press to exit */
-void outofmemory_cb(gpointer dialog _U_, gint btn _U_, gpointer data _U_)
+static void outofmemory_cb(gpointer dialog _U_, gint btn _U_, gpointer data _U_)
 {
     main_window_exit();
 }
 
+static float
+calc_progbar_val(capture_file *cf, gint64 size, gint64 file_pos, gchar *status_str, gulong status_size)
+{
+  float   progbar_val;
+
+  progbar_val = (gfloat) file_pos / (gfloat) size;
+  if (progbar_val > 1.0) {
+
+    /*  The file probably grew while we were reading it.
+     *  Update file size, and try again.
+     */
+    size = wtap_file_size(cf->wth, NULL);
+
+    /*  Another possibility is that we're reading a compressed file and we've
+     *  read more (uncompressed) data from the file than exists in the
+     *  (compressed) file.  So check how much data we've actually read.
+     *
+     *  This is inside this "if val > 1.0" check to avoid the lseek() when
+     *  reading uncompressed files.  Testing has (thus far) shown no progress
+     *  bar weirdness resulting from switching from the data offset (when
+     *  reading the first part of the file) to the real file position.
+     */
+    file_pos = wtap_read_so_far(cf->wth, NULL);
+
+    if (size >= 0)
+      progbar_val = (gfloat) file_pos / (gfloat) size;
+
+    /*  If it's still > 1, either "wtap_file_size()" 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 (progbar_val > 1.0f)
+      progbar_val = 1.0f;
+  }
+
+  g_snprintf(status_str, status_size,
+            "%" G_GINT64_MODIFIER "dKB of %" G_GINT64_MODIFIER "dKB",
+            file_pos / 1024, size / 1024);
+
+  return progbar_val;
+}
+
 cf_read_status_t
-cf_read(capture_file *cf)
+cf_read(capture_file *cf, gboolean from_save)
 {
   int         err;
   gchar       *err_info;
@@ -417,7 +529,6 @@ cf_read(capture_file *cf)
   progdlg_t *volatile progbar = NULL;
   gboolean     stop_flag;
   volatile gint64 size;
-  gint64       file_pos;
   volatile float progbar_val;
   GTimeVal     start_time;
   gchar        status_str[100];
@@ -426,18 +537,18 @@ cf_read(capture_file *cf)
   dfilter_t   *dfcode;
   gboolean    filtering_tap_listeners;
   guint       tap_flags;
+  volatile int count = 0;
 #ifdef HAVE_LIBPCAP
   volatile int displayed_once = 0;
 #endif
+  gboolean compiled;
 
   /* Compile the current display filter.
    * We assume this will not fail since cf->dfilter is only set in
    * cf_filter IFF the filter was valid.
    */
-  dfcode=NULL;
-  if(cf->dfilter){
-    dfilter_compile(cf->dfilter, &dfcode);
-  }
+  compiled = dfilter_compile(cf->dfilter, &dfcode);
+  g_assert(!cf->dfilter || (compiled && dfcode));
 
   /* Do we have any tap listeners with filters? */
   filtering_tap_listeners = have_filtering_tap_listeners();
@@ -445,14 +556,15 @@ cf_read(capture_file *cf)
   /* Get the union of the flags for all tap listeners. */
   tap_flags = union_of_tap_listener_flags();
 
-  cum_bytes=0;
-
   reset_tap_listeners();
 
-  cf_callback_invoke(cf_cb_file_read_start, cf);
-
   name_ptr = get_basename(cf->filename);
 
+  if (from_save == FALSE)
+    cf_callback_invoke(cf_cb_file_read_started, cf);
+  else
+    cf_callback_invoke(cf_cb_file_save_started, (gpointer)name_ptr);
+
   /* Find the size of the file. */
   size = wtap_file_size(cf->wth, NULL);
 
@@ -460,9 +572,11 @@ cf_read(capture_file *cf)
   progbar_nextstep = 0;
   /* When we reach the value that triggers a progress bar update,
      bump that value by this amount. */
-  if (size >= 0)
+  if (size >= 0){
     progbar_quantum = size/N_PROGBAR_UPDATES;
-  else
+    if (progbar_quantum < MIN_QUANTUM)
+      progbar_quantum = MIN_QUANTUM;
+  }else
     progbar_quantum = 0;
   /* Progress so far. */
   progbar_val = 0.0f;
@@ -478,14 +592,18 @@ cf_read(capture_file *cf)
 
   while ((wtap_read(cf->wth, &err, &err_info, &data_offset))) {
     if (size >= 0) {
+      count++;
       /* Create the progress bar if necessary.
-         We check on every iteration of the loop, so that it takes no
-         longer than the standard time to create it (otherwise, for a
-         large file, we might take considerably longer than that standard
-         time in order to get to the next progress bar step). */
-      if (progbar == NULL) {
-        progbar = delayed_create_progress_dlg("Loading", name_ptr,
-          TRUE, &stop_flag, &start_time, progbar_val);
+       * Check whether it should be created or not every MIN_NUMBER_OF_PACKET
+       */
+      if ((progbar == NULL) && !(count % MIN_NUMBER_OF_PACKET)){
+        progbar_val = calc_progbar_val(cf, size, data_offset, status_str, sizeof(status_str));
+        if (from_save == FALSE)
+          progbar = delayed_create_progress_dlg("Loading", name_ptr,
+                                                TRUE, &stop_flag, &start_time, progbar_val);
+        else
+          progbar = delayed_create_progress_dlg("Saving", name_ptr,
+                                                TRUE, &stop_flag, &start_time, progbar_val);
       }
 
       /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
@@ -494,46 +612,31 @@ cf_read(capture_file *cf)
          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 (data_offset >= progbar_nextstep) {
-          file_pos = wtap_read_so_far(cf->wth, NULL);
-          progbar_val = (gfloat) file_pos / (gfloat) size;
-          if (progbar_val > 1.0) {
-            /* The file probably grew while we were reading it.
-               Update file size, and try again. */
-            size = wtap_file_size(cf->wth, NULL);
-            if (size >= 0)
-              progbar_val = (gfloat) file_pos / (gfloat) size;
-            /* If it's still > 1, either "wtap_file_size()" 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 (progbar_val > 1.0f)
-              progbar_val = 1.0f;
-          }
-          if (progbar != NULL) {
-              /* update the packet lists content on the first run or frequently on very large files */
-              /* (on smaller files the display update takes longer than reading the file) */
+        if (progbar != NULL) {
+          progbar_val = calc_progbar_val(cf, size, data_offset, status_str, sizeof(status_str));
+          /* update the packet lists content on the first run or frequently on very large files */
+          /* (on smaller files the display update takes longer than reading the file) */
 #ifdef HAVE_LIBPCAP
-              if (progbar_quantum > 500000 || displayed_once == 0) {
-                  if ((auto_scroll_live || displayed_once == 0 || cf->displayed_count < 1000) && cf->plist_end != NULL) {
-                      displayed_once = 1;
+          if (progbar_quantum > 500000 || displayed_once == 0) {
+            if ((auto_scroll_live || displayed_once == 0 || cf->displayed_count < 1000) && cf->plist_end != NULL) {
+              displayed_once = 1;
 #ifdef NEW_PACKET_LIST
-                     /* XXX - Add move to end function call.  Freeze/thaw if
-                     * necessary. */
+              new_packet_list_thaw();
+              if (auto_scroll_live)
+                new_packet_list_moveto_end();
+              new_packet_list_freeze();
 #else
-                      packet_list_thaw();
-                      if (auto_scroll_live)
-                          packet_list_moveto_end();
-                      packet_list_freeze();
+              packet_list_thaw();
+              if (auto_scroll_live)
+                packet_list_moveto_end();
+              packet_list_freeze();
 #endif /* NEW_PACKET_LIST */
-                  }
-             }
-#endif /* HAVE_LIBPCAP */
-            g_snprintf(status_str, sizeof(status_str),
-                       "%" G_GINT64_MODIFIER "dKB of %" G_GINT64_MODIFIER "dKB",
-                       file_pos / 1024, size / 1024);
-            update_progress_dlg(progbar, progbar_val, status_str);
+            }
           }
-         progbar_nextstep += progbar_quantum;
+#endif /* HAVE_LIBPCAP */
+          update_progress_dlg(progbar, progbar_val, status_str);
+        }
+        progbar_nextstep += progbar_quantum;
       }
     }
 
@@ -547,27 +650,27 @@ cf_read(capture_file *cf)
       break;
     }
     TRY {
-        read_packet(cf, dfcode, filtering_tap_listeners, tap_flags, data_offset);
+      read_packet(cf, dfcode, filtering_tap_listeners, tap_flags, data_offset);
     }
     CATCH(OutOfMemoryError) {
-        gpointer dialog;
-
-        dialog = simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
-              "%sOut Of Memory!%s\n"
-              "\n"
-              "Sorry, but Wireshark has to terminate now!\n"
-              "\n"
-              "Some infos / workarounds can be found at:\n"
-              "http://wiki.wireshark.org/KnownBugs/OutOfMemory",
-              simple_dialog_primary_start(), simple_dialog_primary_end());
-        /* we have to terminate, as we cannot recover from the memory error */
-        simple_dialog_set_cb(dialog, outofmemory_cb, NULL);
-        while(1) {
-            main_window_update();
-            /* XXX - how to avoid a busy wait? */
-            /* Sleep(100); */
-        };
-        break;
+      gpointer dialog;
+
+      dialog = simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
+                             "%sOut Of Memory!%s\n"
+                             "\n"
+                             "Sorry, but Wireshark has to terminate now!\n"
+                             "\n"
+                             "Some infos / workarounds can be found at:\n"
+                             "http://wiki.wireshark.org/KnownBugs/OutOfMemory",
+                             simple_dialog_primary_start(), simple_dialog_primary_end());
+      /* we have to terminate, as we cannot recover from the memory error */
+      simple_dialog_set_cb(dialog, outofmemory_cb, NULL);
+      while(1) {
+        main_window_update();
+        /* XXX - how to avoid a busy wait? */
+        /* Sleep(100); */
+      };
+      break;
     }
     ENDTRY;
   }
@@ -591,6 +694,9 @@ cf_read(capture_file *cf)
    * don't need after the sequential run-through of the packets. */
   postseq_cleanup_all_protocols();
 
+  /* compute the time it took to load the file */
+  compute_elapsed(&start_time);
+
   /* 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
@@ -605,8 +711,10 @@ cf_read(capture_file *cf)
 #else
   packet_list_thaw();
 #endif
-
-  cf_callback_invoke(cf_cb_file_read_finished, cf);
+  if (from_save == FALSE)
+    cf_callback_invoke(cf_cb_file_read_finished, cf);
+  else
+    cf_callback_invoke(cf_cb_file_save_finished, cf);
 
   /* If we have any displayed packets to select, select the first of those
      packets by making the first row the selected row. */
@@ -620,13 +728,13 @@ cf_read(capture_file *cf)
 
   if(stop_flag) {
     simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
-          "%sFile loading was cancelled!%s\n"
-          "\n"
-                 "The remaining packets in the file were discarded.\n"
-          "\n"
-          "As a lot of packets from the original file will be missing,\n"
-                 "remember to be careful when saving the current content to a file.\n",
-          simple_dialog_primary_start(), simple_dialog_primary_end());
+                  "%sFile loading was cancelled!%s\n"
+                  "\n"
+                  "The remaining packets in the file were discarded.\n"
+                  "\n"
+                  "As a lot of packets from the original file will be missing,\n"
+                  "remember to be careful when saving the current content to a file.\n",
+                  simple_dialog_primary_start(), simple_dialog_primary_end());
     return CF_READ_ERROR;
   }
 
@@ -638,34 +746,34 @@ cf_read(capture_file *cf)
 
     case WTAP_ERR_UNSUPPORTED_ENCAP:
       g_snprintf(errmsg_errno, sizeof(errmsg_errno),
-               "The capture file has a packet with a network type that Wireshark doesn't support.\n(%s)",
-               err_info);
+                 "The capture file has a packet with a network type that Wireshark doesn't support.\n(%s)",
+                 err_info);
       g_free(err_info);
       errmsg = errmsg_errno;
       break;
 
     case WTAP_ERR_CANT_READ:
       errmsg = "An attempt to read from the capture file failed for"
-               " some unknown reason.";
+        " some unknown reason.";
       break;
 
     case WTAP_ERR_SHORT_READ:
       errmsg = "The capture file appears to have been cut short"
-               " in the middle of a packet.";
+        " in the middle of a packet.";
       break;
 
     case WTAP_ERR_BAD_RECORD:
       g_snprintf(errmsg_errno, sizeof(errmsg_errno),
-               "The capture file appears to be damaged or corrupt.\n(%s)",
-               err_info);
+                 "The capture file appears to be damaged or corrupt.\n(%s)",
+                 err_info);
       g_free(err_info);
       errmsg = errmsg_errno;
       break;
 
     default:
       g_snprintf(errmsg_errno, sizeof(errmsg_errno),
-              "An error occurred while reading the"
-              " capture file: %s.", wtap_strerror(err));
+                 "An error occurred while reading the"
+                 " capture file: %s.", wtap_strerror(err));
       errmsg = errmsg_errno;
       break;
     }
@@ -694,15 +802,14 @@ cf_continue_tail(capture_file *cf, volatile int to_read, int *err)
   dfilter_t   *dfcode;
   gboolean filtering_tap_listeners;
   guint tap_flags;
+  gboolean compiled;
 
   /* Compile the current display filter.
    * We assume this will not fail since cf->dfilter is only set in
    * cf_filter IFF the filter was valid.
    */
-  dfcode=NULL;
-  if(cf->dfilter){
-    dfilter_compile(cf->dfilter, &dfcode);
-  }
+  compiled = dfilter_compile(cf->dfilter, &dfcode);
+  g_assert(!cf->dfilter || (compiled && dfcode));
 
   /* Do we have any tap listeners with filters? */
   filtering_tap_listeners = have_filtering_tap_listeners();
@@ -713,7 +820,9 @@ cf_continue_tail(capture_file *cf, volatile int to_read, int *err)
   *err = 0;
 
 #ifdef NEW_PACKET_LIST
-  new_packet_list_freeze();
+  new_packet_list_check_end();
+  /* Don't freeze/thaw the list when doing live capture */
+  /*new_packet_list_freeze();*/
 #else
   packet_list_check_end();
   packet_list_freeze();
@@ -721,46 +830,51 @@ cf_continue_tail(capture_file *cf, volatile int to_read, int *err)
 
   /*g_log(NULL, G_LOG_LEVEL_MESSAGE, "cf_continue_tail: %u new: %u", cf->count, to_read);*/
 
-  while (to_read != 0 && (wtap_read(cf->wth, err, &err_info, &data_offset))) {
+  while (to_read != 0) {
+    wtap_cleareof(cf->wth);
+    if (!wtap_read(cf->wth, err, &err_info, &data_offset)) {
+      break;
+    }
     if (cf->state == FILE_READ_ABORTED) {
       /* Well, the user decided to exit Wireshark.  Break out of the
          loop, and let the code below (which is called even if there
-        aren't any packets left to read) exit. */
+         aren't any packets left to read) exit. */
       break;
     }
     TRY{
-        if (read_packet(cf, dfcode, filtering_tap_listeners, tap_flags,
-                        data_offset) != -1) {
-            newly_displayed_packets++;
-        }
+      if (read_packet(cf, dfcode, filtering_tap_listeners, tap_flags,
+                      data_offset) != -1) {
+        newly_displayed_packets++;
+      }
     }
     CATCH(OutOfMemoryError) {
-        gpointer dialog;
-
-        dialog = simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
-              "%sOut Of Memory!%s\n"
-              "\n"
-              "Sorry, but Wireshark has to terminate now!\n"
-              "\n"
-              "The capture file is not lost, it can be found at:\n"
-              "%s\n"
-              "\n"
-              "Some infos / workarounds can be found at:\n"
-              "http://wiki.wireshark.org/KnownBugs/OutOfMemory",
-              simple_dialog_primary_start(), simple_dialog_primary_end(), cf->filename);
-        /* we have to terminate, as we cannot recover from the memory error */
-        simple_dialog_set_cb(dialog, outofmemory_cb, NULL);
-        while(1) {
-            main_window_update();
-            /* XXX - how to avoid a busy wait? */
-            /* Sleep(100); */
-        };
+      gpointer dialog;
+
+      dialog = simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
+                             "%sOut Of Memory!%s\n"
+                             "\n"
+                             "Sorry, but Wireshark has to terminate now!\n"
+                             "\n"
+                             "The capture file is not lost, it can be found at:\n"
+                             "%s\n"
+                             "\n"
+                             "Some infos / workarounds can be found at:\n"
+                             "http://wiki.wireshark.org/KnownBugs/OutOfMemory",
+                             simple_dialog_primary_start(), simple_dialog_primary_end(), cf->filename);
+      /* we have to terminate, as we cannot recover from the memory error */
+      simple_dialog_set_cb(dialog, outofmemory_cb, NULL);
+      while(1) {
+        main_window_update();
+        /* XXX - how to avoid a busy wait? */
+        /* Sleep(100); */
+      };
 #ifdef NEW_PACKET_LIST
-        new_packet_list_thaw();
+      /* Don't freeze/thaw the list when doing live capture */
+      /*new_packet_list_thaw();*/
 #else
-       packet_list_thaw();
+      packet_list_thaw();
 #endif
-        return CF_READ_ABORTED;
+      return CF_READ_ABORTED;
     }
     ENDTRY;
     to_read--;
@@ -772,23 +886,31 @@ cf_continue_tail(capture_file *cf, volatile int to_read, int *err)
   }
 
   /*g_log(NULL, G_LOG_LEVEL_MESSAGE, "cf_continue_tail: count %u state: %u err: %u",
-         cf->count, cf->state, *err);*/
+    cf->count, cf->state, *err);*/
 
 #ifdef NEW_PACKET_LIST
-  new_packet_list_thaw();
+  /* Don't freeze/thaw the list when doing live capture */
+  /*new_packet_list_thaw();*/
+  /* With the new packet list the first packet
+   * isn't automatically selected.
+   */
+  if(!cf->current_frame)
+    new_packet_list_select_first_row();
 #else
   /* XXX - this causes "flickering" of the list */
   packet_list_thaw();
 #endif
 
-#ifndef NEW_PACKET_LIST
   /* moving to the end of the packet list - if the user requested so and
-     we have some new packets.
-     this doesn't seem to work well with a frozen GTK_Clist, so do this after
-     packet_list_thaw() is done, see bugzilla 1188 */
-  /* XXX - this cheats and looks inside the packet list to find the final
-     row number. */
+     we have some new packets. */
   if (newly_displayed_packets && auto_scroll_live && cf->plist_end != NULL)
+#ifdef NEW_PACKET_LIST
+      new_packet_list_moveto_end();
+#else
+    /* this doesn't seem to work well with a frozen GTK_Clist, so do this after
+       packet_list_thaw() is done, see bugzilla 1188 */
+    /* XXX - this cheats and looks inside the packet list to find the final
+       row number. */
     packet_list_moveto_end();
 #endif /* NEW_PACKET_LIST */
 
@@ -802,14 +924,19 @@ cf_continue_tail(capture_file *cf, volatile int to_read, int *err)
   } else if (*err != 0) {
     /* We got an error reading the capture file.
        XXX - pop up a dialog box instead? */
-       g_warning("Error \"%s\" while reading: \"%s\"\n",
-               wtap_strerror(*err), cf->filename);
+    g_warning("Error \"%s\" while reading: \"%s\"\n",
+        wtap_strerror(*err), cf->filename);
 
     return CF_READ_ERROR;
   } else
     return CF_READ_OK;
 }
 
+void
+cf_fake_continue_tail(capture_file *cf) {
+  cf->state = FILE_READ_DONE;
+}
+
 cf_read_status_t
 cf_finish_tail(capture_file *cf, int *err)
 {
@@ -818,15 +945,14 @@ cf_finish_tail(capture_file *cf, int *err)
   dfilter_t   *dfcode;
   gboolean filtering_tap_listeners;
   guint tap_flags;
+  gboolean compiled;
 
   /* Compile the current display filter.
    * We assume this will not fail since cf->dfilter is only set in
    * cf_filter IFF the filter was valid.
    */
-  dfcode=NULL;
-  if(cf->dfilter){
-    dfilter_compile(cf->dfilter, &dfcode);
-  }
+  compiled = dfilter_compile(cf->dfilter, &dfcode);
+  g_assert(!cf->dfilter || (compiled && dfcode));
 
   /* Do we have any tap listeners with filters? */
   filtering_tap_listeners = have_filtering_tap_listeners();
@@ -840,7 +966,9 @@ cf_finish_tail(capture_file *cf, int *err)
   }
 
 #ifdef NEW_PACKET_LIST
-  new_packet_list_freeze();
+  new_packet_list_check_end();
+  /* Don't freeze/thaw the list when doing live capture */
+  /*new_packet_list_freeze();*/
 #else
   packet_list_check_end();
   packet_list_freeze();
@@ -850,7 +978,7 @@ cf_finish_tail(capture_file *cf, int *err)
     if (cf->state == FILE_READ_ABORTED) {
       /* Well, the user decided to abort the read.  Break out of the
          loop, and let the code below (which is called even if there
-        aren't any packets left to read) exit. */
+     aren't any packets left to read) exit. */
       break;
     }
     read_packet(cf, dfcode, filtering_tap_listeners, tap_flags, data_offset);
@@ -862,7 +990,8 @@ cf_finish_tail(capture_file *cf, int *err)
   }
 
 #ifdef NEW_PACKET_LIST
-  new_packet_list_thaw();
+  /* Don't freeze/thaw the list when doing live capture */
+  /*new_packet_list_thaw();*/
 #else
   packet_list_thaw();
 #endif
@@ -877,8 +1006,10 @@ cf_finish_tail(capture_file *cf, int *err)
     return CF_READ_ABORTED;
   }
 
-#ifndef NEW_PACKET_LIST
   if (auto_scroll_live && cf->plist_end != NULL)
+#ifdef NEW_PACKET_LIST
+    new_packet_list_moveto_end();
+#else
     /* XXX - this cheats and looks inside the packet list to find the final
        row number. */
     packet_list_moveto_end();
@@ -927,152 +1058,238 @@ cf_get_display_name(capture_file *cf)
   } else {
     /* The file we read is a temporary file from a live capture;
        we don't mention its name. */
-    displayname = "(Untitled)";
+    if (cf->source) {
+      displayname = cf->source;
+    } else {
+      displayname = "(Untitled)";
+    }
   }
   return displayname;
 }
 
+void cf_set_tempfile_source(capture_file *cf, gchar *source) {
+  if (cf->source) {
+    g_free(cf->source);
+  }
+
+  if (source) {
+    cf->source = g_strdup(source);
+  } else {
+    cf->source = g_strdup("");
+  }
+}
+
+const gchar *cf_get_tempfile_source(capture_file *cf) {
+  if (!cf->source) {
+    return "";
+  }
+
+  return cf->source;
+}
+
 /* XXX - use a macro instead? */
 int
 cf_get_packet_count(capture_file *cf)
 {
-    return cf->count;
+  return cf->count;
 }
 
 /* XXX - use a macro instead? */
 void
 cf_set_packet_count(capture_file *cf, int packet_count)
 {
-    cf->count = packet_count;
+  cf->count = packet_count;
 }
 
 /* XXX - use a macro instead? */
 gboolean
 cf_is_tempfile(capture_file *cf)
 {
-    return cf->is_tempfile;
+  return cf->is_tempfile;
 }
 
 void cf_set_tempfile(capture_file *cf, gboolean is_tempfile)
 {
-    cf->is_tempfile = is_tempfile;
+  cf->is_tempfile = is_tempfile;
 }
 
 
 /* XXX - use a macro instead? */
 void cf_set_drops_known(capture_file *cf, gboolean drops_known)
 {
-    cf->drops_known = drops_known;
+  cf->drops_known = drops_known;
 }
 
 /* XXX - use a macro instead? */
 void cf_set_drops(capture_file *cf, guint32 drops)
 {
-    cf->drops = drops;
+  cf->drops = drops;
 }
 
 /* XXX - use a macro instead? */
 gboolean cf_get_drops_known(capture_file *cf)
 {
-    return cf->drops_known;
+  return cf->drops_known;
 }
 
 /* XXX - use a macro instead? */
 guint32 cf_get_drops(capture_file *cf)
 {
-    return cf->drops;
+  return cf->drops;
 }
 
 void cf_set_rfcode(capture_file *cf, dfilter_t *rfcode)
 {
-    cf->rfcode = rfcode;
+  cf->rfcode = rfcode;
 }
 
+#ifdef NEW_PACKET_LIST
 static int
 add_packet_to_packet_list(frame_data *fdata, capture_file *cf,
-       dfilter_t *dfcode, gboolean filtering_tap_listeners,
-       guint tap_flags,
-       union wtap_pseudo_header *pseudo_header, const guchar *buf,
-       gboolean refilter)
+    dfilter_t *dfcode, gboolean filtering_tap_listeners,
+    guint tap_flags,
+    union wtap_pseudo_header *pseudo_header, const guchar *buf,
+    gboolean refilter,
+    gboolean add_to_packet_list)
 {
-  gint          row;
-  gboolean     create_proto_tree = FALSE;
-  epan_dissect_t *edt;
+  gboolean  create_proto_tree = FALSE;
+  epan_dissect_t edt;
+  column_info *cinfo;
+  gint row = -1;
 
-  /* just add some value here until we know if it is being displayed or not */
-  fdata->cum_bytes  = cum_bytes + fdata->pkt_len;
+  cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
 
-  /* If we don't have the time stamp of the first packet in the
-     capture, it's because this is the first packet.  Save the time
-     stamp of this packet as the time stamp of the first packet. */
-  if (nstime_is_unset(&first_ts)) {
-    first_ts  = fdata->abs_ts;
-  }
-  /* if this frames is marked as a reference time frame, reset
-     firstsec and firstusec to this frame */
-  if(fdata->flags.ref_time){
-    first_ts = fdata->abs_ts;
+  frame_data_set_before_dissect(fdata, &cf->elapsed_time,
+                                &first_ts, &prev_dis_ts, &prev_cap_ts);
+
+  /* If either
+    + we have a display filter and are re-applying it;
+    + we have tap listeners with filters;
+    + we have tap listeners that require a protocol tree;
+
+     allocate a protocol tree root node, so that we'll construct
+     a protocol tree against which a filter expression can be
+     evaluated. */
+  if ((dfcode != NULL && refilter) ||
+      filtering_tap_listeners || (tap_flags & TL_REQUIRES_PROTO_TREE))
+      create_proto_tree = TRUE;
+
+  /* Dissect the frame. */
+  epan_dissect_init(&edt, create_proto_tree, FALSE);
+
+  if (dfcode != NULL && refilter) {
+      epan_dissect_prime_dfilter(&edt, dfcode);
   }
 
-  /* If we don't have the time stamp of the previous displayed packet,
-     it's because this is the first displayed packet.  Save the time
-     stamp of this packet as the time stamp of the previous displayed
-     packet. */
-  if (nstime_is_unset(&prev_dis_ts)) {
-    prev_dis_ts = fdata->abs_ts;
+  tap_queue_init(&edt);
+  epan_dissect_run(&edt, pseudo_header, buf, fdata, cinfo);
+  tap_push_tapped_queue(&edt);
+
+  /* If we have a display filter, apply it if we're refiltering, otherwise
+     leave the "passed_dfilter" flag alone.
+
+     If we don't have a display filter, set "passed_dfilter" to 1. */
+  if (dfcode != NULL) {
+    if (refilter) {
+      fdata->flags.passed_dfilter = dfilter_apply_edt(dfcode, &edt) ? 1 : 0;
+    }
+  } else
+    fdata->flags.passed_dfilter = 1;
+
+  if(fdata->flags.passed_dfilter || fdata->flags.ref_time)
+    cf->displayed_count++;
+
+  if (add_to_packet_list) {
+    /* We fill the needed columns from new_packet_list */
+      row = new_packet_list_append(cinfo, fdata, &edt.pi);
   }
 
-  /* Get the time elapsed between the first packet and this packet. */
-  nstime_delta(&fdata->rel_ts, &fdata->abs_ts, &first_ts);
+  if(fdata->flags.passed_dfilter || fdata->flags.ref_time)
+  {
+    frame_data_set_after_dissect(fdata, &cum_bytes, &prev_dis_ts);
 
-  /* 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 ((gint32)cf->elapsed_time.secs < fdata->rel_ts.secs
-  || ((gint32)cf->elapsed_time.secs == fdata->rel_ts.secs && (gint32)cf->elapsed_time.nsecs < fdata->rel_ts.nsecs)) {
-    cf->elapsed_time = fdata->rel_ts;
+    /* If we haven't yet seen the first frame, this is it.
+
+       XXX - we must do this before we add the row to the display,
+       as, if the display's GtkCList's selection mode is
+       GTK_SELECTION_BROWSE, when the first entry is added to it,
+       "cf_select_packet()" will be called, and it will fetch the row
+       data for the 0th row, and will get a null pointer rather than
+       "fdata", as "gtk_clist_append()" won't yet have returned and
+       thus "gtk_clist_set_row_data()" won't yet have been called.
+
+       We thus need to leave behind bread crumbs so that
+       "cf_select_packet()" can find this frame.  See the comment
+       in "cf_select_packet()". */
+    if (cf->first_displayed == NULL)
+      cf->first_displayed = fdata;
+
+    /* This is the last frame we've seen so far. */
+    cf->last_displayed = fdata;
   }
 
-  /* Get the time elapsed between the previous displayed packet and
-     this packet. */
-  nstime_delta(&fdata->del_dis_ts, &fdata->abs_ts, &prev_dis_ts);
+  epan_dissect_cleanup(&edt);
+  return row;
+}
+
+#else
+
+static int
+add_packet_to_packet_list(frame_data *fdata, capture_file *cf,
+    dfilter_t *dfcode, gboolean filtering_tap_listeners,
+    guint tap_flags,
+    union wtap_pseudo_header *pseudo_header, const guchar *buf,
+    gboolean refilter,
+    gboolean add_to_packet_list _U_)
+{
+  gboolean  create_proto_tree = FALSE;
+  epan_dissect_t edt;
+  column_info *cinfo;
+  gint row = -1;
+
+  cinfo = &cf->cinfo;
+
+  /* just add some value here until we know if it is being displayed or not */
+  fdata->cum_bytes  = cum_bytes + fdata->pkt_len;
+
+  frame_data_set_before_dissect(fdata, &cf->elapsed_time,
+                                &first_ts, &prev_dis_ts, &prev_cap_ts);
 
   /* If either
 
-       we have a display filter and are re-applying it;
+    we have a display filter and are re-applying it;
 
-       we have a list of color filters;
+    we have a list of color filters;
 
-       we have tap listeners with filters;
+    we have tap listeners with filters;
 
     we have tap listeners that require a protocol tree;
 
-       we have custom columns;
+    we have custom columns;
 
      allocate a protocol tree root node, so that we'll construct
      a protocol tree against which a filter expression can be
      evaluated. */
-  if ((dfcode != NULL && refilter) || color_filters_used() ||
-      filtering_tap_listeners || (tap_flags & TL_REQUIRES_PROTO_TREE) ||
-      have_custom_cols(&cf->cinfo))
-         create_proto_tree = TRUE;
+  if ((dfcode != NULL && refilter) ||
+      color_filters_used() ||
+      have_custom_cols(cinfo) ||
+      filtering_tap_listeners || (tap_flags & TL_REQUIRES_PROTO_TREE))
+      create_proto_tree = TRUE;
 
   /* Dissect the frame. */
-  edt = epan_dissect_new(create_proto_tree, FALSE);
+  epan_dissect_init(&edt, create_proto_tree, FALSE);
 
   if (dfcode != NULL && refilter) {
-      epan_dissect_prime_dfilter(edt, dfcode);
-  }
-  /* prepare color filters */
-  if (color_filters_used()) {
-      color_filters_prime_edt(edt);
+      epan_dissect_prime_dfilter(&edt, dfcode);
   }
 
-  col_custom_prime_edt(edt, &cf->cinfo);
+  /* prepare color filters */
+  color_filters_prime_edt(&edt);
+  col_custom_prime_edt(&edt, cinfo);
 
-  tap_queue_init(edt);
-  epan_dissect_run(edt, pseudo_header, buf, fdata, &cf->cinfo);
-  tap_push_tapped_queue(edt);
+  tap_queue_init(&edt);
+  epan_dissect_run(&edt, pseudo_header, buf, fdata, cinfo);
+  tap_push_tapped_queue(&edt);
 
   /* If we have a display filter, apply it if we're refiltering, otherwise
      leave the "passed_dfilter" flag alone.
@@ -1080,25 +1297,16 @@ add_packet_to_packet_list(frame_data *fdata, capture_file *cf,
      If we don't have a display filter, set "passed_dfilter" to 1. */
   if (dfcode != NULL) {
     if (refilter) {
-      fdata->flags.passed_dfilter = dfilter_apply_edt(dfcode, edt) ? 1 : 0;
+      fdata->flags.passed_dfilter = dfilter_apply_edt(dfcode, &edt) ? 1 : 0;
     }
   } else
     fdata->flags.passed_dfilter = 1;
 
-  if( (fdata->flags.passed_dfilter) || (edt->pi.fd->flags.ref_time) ){
-    /* This frame either passed the display filter list or is marked as
-       a time reference frame.  All time reference frames are displayed
-       even if they dont pass the display filter */
-    if(edt->pi.fd->flags.ref_time){
-      /* if this was a TIME REF frame we should reset the cul bytes field */
-      cum_bytes = fdata->pkt_len;
-      fdata->cum_bytes =  cum_bytes;
-    } else {
-      /* increase cum_bytes with this packets length */
-      cum_bytes += fdata->pkt_len;
-    }
+  if( (fdata->flags.passed_dfilter) || (fdata->flags.ref_time) )
+  {
+    frame_data_set_after_dissect(fdata, &cum_bytes, &prev_dis_ts);
 
-    epan_dissect_fill_in_columns(edt);
+    epan_dissect_fill_in_columns(&edt, FALSE, TRUE);
 
     /* If we haven't yet seen the first frame, this is it.
 
@@ -1119,40 +1327,28 @@ 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;
 
-#ifdef NEW_PACKET_LIST
-    /* This function returns the color_t that was applied to the packet (in
-     * the old packet list).  Applying the color to the packet is only done
-     * in the following function when not using the new packet list. */
-    fdata->color_filter = color_filters_colorize_packet(0, edt); 
-
-    row = new_packet_list_append(&cf->cinfo, fdata);
-#else
-    row = packet_list_append(cf->cinfo.col_data, fdata);
+    row = packet_list_append(cinfo->col_data, fdata);
 
     /* colorize packet: first apply color filters
      * then if packet is marked, use preferences to overwrite color
      * we do both to make sure that when a packet gets un-marked, the
      * color will be correctly set (fixes bug 2038)
      */
-     fdata->color_filter = color_filters_colorize_packet(row, edt);
+     fdata->color_filter = color_filters_colorize_packet(row, &edt);
      if (fdata->flags.marked) {
        packet_list_set_colors(row, &prefs.gui_marked_fg, &prefs.gui_marked_bg);
      }
-#endif /* NEW_PACKET_LIST */
-
-    /* Set the time of the previous displayed frame to the time of this
-       frame. */
-    prev_dis_ts = fdata->abs_ts;
+     if (fdata->flags.ignored) {
+       packet_list_set_colors(row, &prefs.gui_ignored_fg, &prefs.gui_ignored_bg);
+     }
 
     cf->displayed_count++;
-  } 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;
   }
-  epan_dissect_free(edt);
+
+  epan_dissect_cleanup(&edt);
   return row;
 }
+#endif
 
 /* read in a new packet */
 /* returns the row of the new packet in the packet list or -1 if not displayed */
@@ -1165,12 +1361,12 @@ read_packet(capture_file *cf, dfilter_t *dfcode,
   const guchar *buf = wtap_buf_ptr(cf->wth);
   frame_data   *fdata;
   int           passed;
-  frame_data   *plist_end;
-  epan_dissect_t *edt;
-  int row = -1;
+  int           row = -1;
 
-  /* Allocate the next list entry, and add it to the list. 
-   * memory chunks have been deprecated in favor of the slice allocator, 
+  cf->count++;
+
+  /* Allocate the next list entry, and add it to the list.
+   * memory chunks have been deprecated in favor of the slice allocator,
    * which has been added in 2.10
    */
 #if GLIB_CHECK_VERSION(2,10,0)
@@ -1178,54 +1374,38 @@ read_packet(capture_file *cf, dfilter_t *dfcode,
 #else
   fdata = g_mem_chunk_alloc(cf->plist_chunk);
 #endif
-  fdata->num = 0;
-  fdata->next = NULL;
-  fdata->prev = NULL;
-  fdata->pfd  = NULL;
-  fdata->pkt_len  = phdr->len;
-  fdata->cap_len  = phdr->caplen;
-  fdata->file_off = offset;
-  fdata->lnk_t = phdr->pkt_encap;
-  fdata->flags.encoding = CHAR_ASCII;
-  fdata->flags.visited = 0;
-  fdata->flags.marked = 0;
-  fdata->flags.ref_time = 0;
-  fdata->color_filter = NULL;
-
-  fdata->abs_ts.secs = phdr->ts.secs;
-  fdata->abs_ts.nsecs = phdr->ts.nsecs;
-
-  if (cf->plist_end != NULL)
-    nstime_delta(&fdata->del_cap_ts, &fdata->abs_ts, &cf->plist_end->abs_ts);
-  else
-    nstime_set_zero(&fdata->del_cap_ts);
+
+  frame_data_init(fdata, cf->count, phdr, offset, cum_bytes);
+
+#ifdef NEW_PACKET_LIST
+  fdata->col_text_len = se_alloc0(sizeof(fdata->col_text_len) * (cf->cinfo.num_cols));
+  fdata->col_text = se_alloc0(sizeof(fdata->col_text) * (cf->cinfo.num_cols));
+#endif
 
   passed = TRUE;
   if (cf->rfcode) {
-    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);
+    epan_dissect_t edt;
+    epan_dissect_init(&edt, 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_cleanup(&edt);
   }
+
   if (passed) {
-    plist_end = cf->plist_end;
-    fdata->prev = plist_end;
-    if (plist_end != NULL)
-      plist_end->next = fdata;
-    else
-      cf->plist = fdata;
-    cf->plist_end = fdata;
+    cap_file_add_fdata(cf, fdata);
+
+    cf->f_datalen = offset + fdata->cap_len;
 
-    cf->count++;
-    cf->f_datalen = offset + phdr->caplen;
-    fdata->num = cf->count;
     if (!cf->redissecting) {
       row = add_packet_to_packet_list(fdata, cf, dfcode,
                                       filtering_tap_listeners, tap_flags,
-                                      pseudo_header, buf, TRUE);
+                                      pseudo_header, buf, TRUE, TRUE);
     }
   } else {
+    /* We didn't pass read filter so roll back count */
+    cf->count--;
+
     /* XXX - if we didn't have read filters, or if we could avoid
        allocating the "frame_data" structure until we knew whether
        the frame passed the read filter, we could use a G_ALLOC_ONLY
@@ -1235,10 +1415,10 @@ read_packet(capture_file *cf, dfilter_t *dfcode,
        a G_ALLOC_ONLY chunk and read in a huge capture file, it didn't
        seem to save a noticeable amount of time or space. */
 #if GLIB_CHECK_VERSION(2,10,0)
-  /* memory chunks have been deprecated in favor of the slice allocator, 
+  /* memory chunks have been deprecated in favor of the slice allocator,
    * which has been added in 2.10
    */
-       g_slice_free(frame_data,fdata);
+    g_slice_free(frame_data,fdata);
 #else
     g_mem_chunk_free(cf->plist_chunk, fdata);
 #endif
@@ -1306,7 +1486,7 @@ cf_merge_files(char **out_filenamep, int in_file_count,
   pdh = wtap_dump_fdopen(out_fd, file_type,
       merge_select_frame_type(in_file_count, in_files),
       merge_max_snapshot_length(in_file_count, in_files),
-         FALSE /* compressed */, &open_err);
+      FALSE /* compressed */, &open_err);
   if (pdh == NULL) {
     ws_close(out_fd);
     merge_close_in_files(in_file_count, in_files);
@@ -1416,43 +1596,43 @@ cf_merge_files(char **out_filenamep, int in_file_count,
      */
     for (i = 0; i < in_file_count; i++) {
       if (in_files[i].state == GOT_ERROR) {
-       /* Put up a message box noting that a read failed somewhere along
-          the line. */
-       switch (read_err) {
-
-       case WTAP_ERR_UNSUPPORTED_ENCAP:
-         g_snprintf(errmsg_errno, sizeof(errmsg_errno),
-                  "The capture file %%s has a packet with a network type that Wireshark doesn't support.\n(%s)",
-                  err_info);
-         g_free(err_info);
-         errmsg = errmsg_errno;
-         break;
-
-       case WTAP_ERR_CANT_READ:
-         errmsg = "An attempt to read from the capture file %s failed for"
-                  " some unknown reason.";
-         break;
-
-       case WTAP_ERR_SHORT_READ:
-         errmsg = "The capture file %s appears to have been cut short"
-                  " in the middle of a packet.";
-         break;
-
-       case WTAP_ERR_BAD_RECORD:
-         g_snprintf(errmsg_errno, sizeof(errmsg_errno),
-                  "The capture file %%s appears to be damaged or corrupt.\n(%s)",
-                  err_info);
-         g_free(err_info);
-         errmsg = errmsg_errno;
-         break;
-
-       default:
-         g_snprintf(errmsg_errno, sizeof(errmsg_errno),
-                  "An error occurred while reading the"
-                  " capture file %%s: %s.", wtap_strerror(read_err));
-         errmsg = errmsg_errno;
-         break;
-       }
+    /* Put up a message box noting that a read failed somewhere along
+       the line. */
+    switch (read_err) {
+
+    case WTAP_ERR_UNSUPPORTED_ENCAP:
+      g_snprintf(errmsg_errno, sizeof(errmsg_errno),
+           "The capture file %%s has a packet with a network type that Wireshark doesn't support.\n(%s)",
+           err_info);
+      g_free(err_info);
+      errmsg = errmsg_errno;
+      break;
+
+    case WTAP_ERR_CANT_READ:
+      errmsg = "An attempt to read from the capture file %s failed for"
+           " some unknown reason.";
+      break;
+
+    case WTAP_ERR_SHORT_READ:
+      errmsg = "The capture file %s appears to have been cut short"
+           " in the middle of a packet.";
+      break;
+
+    case WTAP_ERR_BAD_RECORD:
+      g_snprintf(errmsg_errno, sizeof(errmsg_errno),
+           "The capture file %%s appears to be damaged or corrupt.\n(%s)",
+           err_info);
+      g_free(err_info);
+      errmsg = errmsg_errno;
+      break;
+
+    default:
+      g_snprintf(errmsg_errno, sizeof(errmsg_errno),
+           "An error occurred while reading the"
+           " capture file %%s: %s.", wtap_strerror(read_err));
+      errmsg = errmsg_errno;
+      break;
+    }
         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, errmsg, in_files[i].filename);
       }
     }
@@ -1478,6 +1658,7 @@ cf_filter_packets(capture_file *cf, gchar *dftext, gboolean force)
   const char *filter_new = dftext ? dftext : "";
   const char *filter_old = cf->dfilter ? cf->dfilter : "";
   dfilter_t   *dfcode;
+  GTimeVal     start_time;
 
   /* if new filter equals old one, do nothing unless told to do so */
   if (!force && strcmp(filter_new, filter_old) == 0) {
@@ -1500,7 +1681,7 @@ cf_filter_packets(capture_file *cf, gchar *dftext, gboolean force)
       /* The attempt failed; report an error. */
       gchar *safe_dftext = simple_dialog_format_message(dftext);
       gchar *safe_dfilter_error_msg = simple_dialog_format_message(
-         dfilter_error_msg);
+      dfilter_error_msg);
       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
           "%s%s%s\n"
           "\n"
@@ -1525,6 +1706,8 @@ cf_filter_packets(capture_file *cf, gchar *dftext, gboolean force)
   /* We have a valid filter.  Replace the current filter. */
   g_free(cf->dfilter);
   cf->dfilter = dftext;
+  g_get_current_time(&start_time);
+
 
   /* Now rescan the packet list, applying the new filter, but not
      throwing away information constructed on a previous pass. */
@@ -1535,9 +1718,8 @@ cf_filter_packets(capture_file *cf, gchar *dftext, gboolean force)
   }
 
   /* Cleanup and release all dfilter resources */
-  if (dfcode != NULL){
-    dfilter_free(dfcode);
-  }
+  dfilter_free(dfcode);
+
   return CF_OK;
 }
 
@@ -1550,7 +1732,12 @@ cf_colorize_packets(capture_file *cf)
 void
 cf_reftime_packets(capture_file *cf)
 {
-  rescan_packets(cf, "Updating Reftime", "all packets", FALSE, FALSE);
+
+#ifdef NEW_PACKET_LIST
+  ref_time_packets(cf);
+#else
+  rescan_packets(cf, "Reprocessing", "all packets", TRUE, TRUE);
+#endif
 }
 
 void
@@ -1559,30 +1746,377 @@ cf_redissect_packets(capture_file *cf)
   rescan_packets(cf, "Reprocessing", "all packets", TRUE, TRUE);
 }
 
+gboolean
+cf_read_frame_r(capture_file *cf, frame_data *fdata,
+                union wtap_pseudo_header *pseudo_header, guint8 *pd)
+{
+  int err;
+  gchar *err_info;
+  char errmsg_errno[1024+1];
+
+  if (!wtap_seek_read(cf->wth, fdata->file_off, pseudo_header, pd,
+                      fdata->cap_len, &err, &err_info)) {
+    switch (err) {
+
+    case WTAP_ERR_UNSUPPORTED_ENCAP:
+      g_snprintf(errmsg_errno, sizeof(errmsg_errno),
+                 "The file \"%%s\" has a packet with a network type that Wireshark doesn't support.\n(%s)",
+                 err_info);
+      g_free(err_info);
+      break;
+
+    case WTAP_ERR_BAD_RECORD:
+      g_snprintf(errmsg_errno, sizeof(errmsg_errno),
+                 "An error occurred while reading from the file \"%%s\": %s.\n(%s)",
+                 wtap_strerror(err), err_info);
+      g_free(err_info);
+      break;
+
+    default:
+      g_snprintf(errmsg_errno, sizeof(errmsg_errno),
+                 "An error occurred while reading from the file \"%%s\": %s.",
+                 wtap_strerror(err));
+      break;
+    }
+    simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, errmsg_errno, cf->filename);
+    return FALSE;
+  }
+  return TRUE;
+}
+
+gboolean
+cf_read_frame(capture_file *cf, frame_data *fdata)
+{
+  return cf_read_frame_r(cf, fdata, &cf->pseudo_header, cf->pd);
+}
+
 /* Rescan the list of packets, reconstructing the CList.
 
    "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.
+   "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
+   any state information they have (because a preference that affects
+   some dissector has changed, meaning some dissector might construct
+   its state differently from the way it was constructed the last time). */
+#ifdef NEW_PACKET_LIST
+static void
+rescan_packets(capture_file *cf, const char *action, const char *action_item,
+        gboolean refilter, gboolean redissect)
+{
+    /* Rescan packets new packet list */
+  frame_data *fdata;
+  progdlg_t  *progbar = NULL;
+  gboolean    stop_flag;
+  int         count;
+  frame_data *selected_frame, *preceding_frame, *following_frame, *prev_frame;
+  int         selected_frame_num, preceding_frame_num, following_frame_num, prev_frame_num;
+  gboolean    selected_frame_seen;
+  int         frame_num;
+  float       progbar_val;
+  GTimeVal    start_time;
+  gchar       status_str[100];
+  int         progbar_nextstep;
+  int         progbar_quantum;
+  dfilter_t   *dfcode;
+  gboolean    filtering_tap_listeners;
+  guint       tap_flags;
+  gboolean    add_to_packet_list = FALSE;
+  gboolean compiled;
+
+  /* Compile the current display filter.
+   * We assume this will not fail since cf->dfilter is only set in
+   * cf_filter IFF the filter was valid.
+   */
+  compiled = dfilter_compile(cf->dfilter, &dfcode);
+  g_assert(!cf->dfilter || (compiled && dfcode));
+
+  /* Do we have any tap listeners with filters? */
+  filtering_tap_listeners = have_filtering_tap_listeners();
+
+  /* Get the union of the flags for all tap listeners. */
+  tap_flags = union_of_tap_listener_flags();
+
+  reset_tap_listeners();
+  /* Which frame, if any, is the currently selected frame?
+     XXX - should the selected frame or the focus frame be the "current"
+     frame, that frame being the one from which "Find Frame" searches
+     start? */
+  selected_frame = cf->current_frame;
+
+  /* Mark frame num as not found */
+  selected_frame_num = -1;
+
+  /* Freeze the packet list while we redo it, so we don't get any
+     screen updates while it happens. */
+  new_packet_list_freeze();
+
+  if (redissect) {
+    /* We need to re-initialize all the state information that protocols
+       keep, because some preference that controls a dissector has changed,
+       which might cause the state information to be constructed differently
+       by that dissector. */
+
+    /* We might receive new packets while redissecting, and we don't
+       want to dissect those before their time. */
+    cf->redissecting = TRUE;
+
+    /* Cleanup all data structures used for dissection. */
+    cleanup_dissection();
+    /* Initialize all data structures used for dissection. */
+    init_dissection();
+
+    /* We need to redissect the packets so we have to discard our old
+     * packet list store. */
+    new_packet_list_clear();
+    add_to_packet_list = TRUE;
+  }
+
+  /* We don't yet know which will be the first and last frames displayed. */
+  cf->first_displayed = NULL;
+  cf->last_displayed = NULL;
+
+  /* We currently don't display any packets */
+  cf->displayed_count = 0;
+
+  /* Iterate through the list of frames.  Call a routine for each frame
+     to check whether it should be displayed and, if so, add it to
+     the display list. */
+  nstime_set_unset(&first_ts);
+  nstime_set_unset(&prev_dis_ts);
+  nstime_set_unset(&prev_cap_ts);
+  cum_bytes = 0;
+
+  /* Update the progress bar when it gets to this value. */
+  progbar_nextstep = 0;
+  /* When we reach the value that triggers a progress bar update,
+     bump that value by this amount. */
+  progbar_quantum = cf->count/N_PROGBAR_UPDATES;
+  /* Count of packets at which we've looked. */
+  count = 0;
+  /* Progress so far. */
+  progbar_val = 0.0f;
+
+  stop_flag = FALSE;
+  g_get_current_time(&start_time);
+
+  /* no previous row yet */
+  frame_num = -1;
+  prev_frame_num = -1;
+  prev_frame = NULL;
+
+  preceding_frame_num = -1;
+  preceding_frame = NULL;
+  following_frame_num = -1;
+  following_frame = NULL;
+
+  selected_frame_seen = FALSE;
+
+  for (fdata = cf->plist_start; fdata != NULL; fdata = fdata->next) {
+    /* Create the progress bar if necessary.
+       We check on every iteration of the loop, so that it takes no
+       longer than the standard time to create it (otherwise, for a
+       large file, we might take considerably longer than that standard
+       time in order to get to the next progress bar step). */
+    if (progbar == NULL)
+      progbar = delayed_create_progress_dlg(action, action_item, TRUE,
+                                            &stop_flag, &start_time,
+                                            progbar_val);
+
+    /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
+       when we update it, we have to run the GTK+ main loop to get it
+       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) {
+      /* let's not divide by zero. I should never be started
+       * with count == 0, so let's assert that
+       */
+      g_assert(cf->count > 0);
+      progbar_val = (gfloat) count / cf->count;
+
+      if (progbar != NULL) {
+        g_snprintf(status_str, sizeof(status_str),
+                  "%4u of %u frames", count, cf->count);
+        update_progress_dlg(progbar, progbar_val, status_str);
+      }
+
+      progbar_nextstep += progbar_quantum;
+    }
+
+    if (stop_flag) {
+      /* Well, the user decided to abort the filtering.  Just stop.
+
+         XXX - go back to the previous filter?  Users probably just
+     want not to wait for a filtering operation to finish;
+     unless we cancel by having no filter, reverting to the
+     previous filter will probably be even more expensive than
+     continuing the filtering, as it involves going back to the
+     beginning and filtering, and even with no filter we currently
+     have to re-generate the entire clist, which is also expensive.
+
+     I'm not sure what Network Monitor does, but it doesn't appear
+     to give you an unfiltered display if you cancel. */
+      break;
+    }
+
+    count++;
+
+    if (redissect) {
+      /* 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_dissection()"), and null out the GSList pointer. */
+      fdata->flags.visited = 0;
+      frame_data_cleanup(fdata);
+
+      /* cleanup_dissection() calls se_free_all();
+       * And after that fdata->col_text (which is allocated using se_alloc0())
+       * no longer points to valid memory.
+       */
+      fdata->col_text_len = se_alloc0(sizeof(fdata->col_text_len) * (cf->cinfo.num_cols));
+      fdata->col_text = se_alloc0(sizeof(fdata->col_text) * (cf->cinfo.num_cols));
+    }
+
+    if (!cf_read_frame(cf, fdata))
+      break; /* error reading the frame */
+
+    /* If the previous frame is displayed, and we haven't yet seen the
+       selected frame, remember that frame - it's the closest one we've
+       yet seen before the selected frame. */
+    if (prev_frame_num != -1 && !selected_frame_seen && prev_frame->flags.passed_dfilter) {
+      preceding_frame_num = prev_frame_num;
+      preceding_frame = prev_frame;
+    }
+    add_packet_to_packet_list(fdata, cf, dfcode, filtering_tap_listeners,
+                                    tap_flags, &cf->pseudo_header, cf->pd,
+                                    refilter,
+                                    add_to_packet_list);
+
+    /* If this frame is displayed, and this is the first frame we've
+       seen displayed after the selected frame, remember this frame -
+       it's the closest one we've yet seen at or after the selected
+       frame. */
+    if (fdata->flags.passed_dfilter && selected_frame_seen && following_frame_num == -1) {
+      following_frame_num = fdata->num;
+      following_frame = fdata;
+    }
+    if (fdata == selected_frame) {
+      selected_frame_seen = TRUE;
+      if (fdata->flags.passed_dfilter)
+          selected_frame_num = fdata->num;
+    }
+
+    /* Remember this frame - it'll be the previous frame
+       on the next pass through the loop. */
+    prev_frame_num = fdata->num;
+    prev_frame = fdata;
+  }
+
+  /* We are done redissecting the packet list. */
+  cf->redissecting = FALSE;
+
+  if (redissect) {
+    /* Clear out what remains of the visited flags and per-frame data
+       pointers.
+
+       XXX - that may cause various forms of bogosity when dissecting
+       these frames, as they won't have been seen by this sequential
+       pass, but the only alternative I see is to keep scanning them
+       even though the user requested that the scan stop, and that
+       would leave the user stuck with an Wireshark grinding on
+       until it finishes.  Should we just stick them with that? */
+    for (; fdata != NULL; fdata = fdata->next) {
+      fdata->flags.visited = 0;
+      frame_data_cleanup(fdata);
+    }
+  }
+
+  /* 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. */
+  if (!add_to_packet_list)
+    new_packet_list_recreate_visible_rows();
+
+  /* Compute the time it took to filter the file */
+  compute_elapsed(&start_time);
+
+  new_packet_list_thaw();
+
+  if (selected_frame_num == -1) {
+    /* The selected frame didn't pass the filter. */
+    if (selected_frame == NULL) {
+      /* That's because there *was* no selected frame.  Make the first
+         displayed frame the current frame. */
+      selected_frame_num = 0;
+    } else {
+      /* Find the nearest displayed frame to the selected frame (whether
+         it's before or after that frame) and make that the current frame.
+         If the next and previous displayed frames are equidistant from the
+         selected frame, choose the next one. */
+      g_assert(following_frame == NULL ||
+               following_frame->num >= selected_frame->num);
+      g_assert(preceding_frame == NULL ||
+               preceding_frame->num <= selected_frame->num);
+      if (following_frame == NULL) {
+        /* No frame after the selected frame passed the filter, so we
+           have to select the last displayed frame before the selected
+           frame. */
+        selected_frame_num = preceding_frame_num;
+        selected_frame = preceding_frame;
+      } else if (preceding_frame == NULL) {
+        /* No frame before the selected frame passed the filter, so we
+           have to select the first displayed frame after the selected
+           frame. */
+        selected_frame_num = following_frame_num;
+        selected_frame = following_frame;
+      } else {
+        /* Frames before and after the selected frame passed the filter, so
+           we'll select the previous frame */
+        selected_frame_num = preceding_frame_num;
+        selected_frame = preceding_frame;
+      }
+    }
+  }
+
+  if (selected_frame_num == -1) {
+    /* There are no frames displayed at all. */
+    cf_unselect_packet(cf);
+  } else {
+    /* Either the frame that was selected passed the filter, or we've
+       found the nearest displayed frame to that frame.  Select it, make
+       it the focus row, and make it visible. */
+    /* Set to invalid to force update of packet list and packet details */
+    cf->current_row = -1;
+    if (selected_frame_num == 0) {
+      new_packet_list_select_first_row();
+    }else{
+      new_packet_list_find_row_from_data(selected_frame, TRUE);
+    }
+  }
+
+  /* Cleanup and release all dfilter resources */
+  dfilter_free(dfcode);
+}
 
-   "refilter" is TRUE if we need to re-evaluate the filter expression.
+#else
 
-   "redissect" is TRUE if we need to make the dissectors reconstruct
-   any state information they have (because a preference that affects
-   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, const char *action_item,
-               gboolean refilter, gboolean redissect)
+        gboolean refilter, gboolean redissect)
 {
   frame_data *fdata;
   progdlg_t  *progbar = NULL;
   gboolean    stop_flag;
   int         count;
-  int         err;
-  gchar      *err_info;
   frame_data *selected_frame, *preceding_frame, *following_frame, *prev_frame;
   int         selected_row, prev_row, preceding_row, following_row;
   gboolean    selected_frame_seen;
@@ -1595,15 +2129,15 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item,
   dfilter_t   *dfcode;
   gboolean    filtering_tap_listeners;
   guint       tap_flags;
+  gboolean    add_to_packet_list = TRUE;
+  gboolean compiled;
 
   /* Compile the current display filter.
    * We assume this will not fail since cf->dfilter is only set in
    * cf_filter IFF the filter was valid.
    */
-  dfcode=NULL;
-  if(cf->dfilter){
-    dfilter_compile(cf->dfilter, &dfcode);
-  }
+  compiled = dfilter_compile(cf->dfilter, &dfcode);
+  g_assert(!cf->dfilter || (compiled && dfcode));
 
   /* Do we have any tap listeners with filters? */
   filtering_tap_listeners = have_filtering_tap_listeners();
@@ -1611,7 +2145,6 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item,
   /* Get the union of the flags for all tap listeners. */
   tap_flags = union_of_tap_listener_flags();
 
-  cum_bytes=0;
   reset_tap_listeners();
   /* Which frame, if any, is the currently selected frame?
      XXX - should the selected frame or the focus frame be the "current"
@@ -1623,6 +2156,13 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item,
      rebuild the clist, however. */
   selected_row = -1;
 
+  /* Freeze the packet list while we redo it, so we don't get any
+     screen updates while it happens. */
+  packet_list_freeze();
+
+  /* Clear it out. */
+  packet_list_clear();
+
   if (redissect) {
     /* We need to re-initialize all the state information that protocols
        keep, because some preference that controls a dissector has changed,
@@ -1633,25 +2173,19 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item,
        want to dissect those before their time. */
     cf->redissecting = TRUE;
 
+    /* Cleanup all data structures used for dissection. */
+    cleanup_dissection();
     /* Initialize all data structures used for dissection. */
     init_dissection();
-  }
-
-  /* Freeze the packet list while we redo it, so we don't get any
-     screen updates while it happens. */
-#ifdef NEW_PACKET_LIST
-  new_packet_list_freeze();
-#else
-  packet_list_freeze();
 
-  /* Clear it out. */
-  packet_list_clear();
-#endif
+  }
 
   /* We don't yet know which will be the first and last frames displayed. */
   cf->first_displayed = NULL;
   cf->last_displayed = NULL;
 
+  reset_elapsed();
+
   /* We currently don't display any packets */
   cf->displayed_count = 0;
 
@@ -1660,6 +2194,8 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item,
      the display list. */
   nstime_set_unset(&first_ts);
   nstime_set_unset(&prev_dis_ts);
+  nstime_set_unset(&prev_cap_ts);
+  cum_bytes = 0;
 
   /* Update the progress bar when it gets to this value. */
   progbar_nextstep = 0;
@@ -1674,7 +2210,7 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item,
   stop_flag = FALSE;
   g_get_current_time(&start_time);
 
-  row = -1;            /* no previous row yet */
+  row = -1;     /* no previous row yet */
   prev_row = -1;
   prev_frame = NULL;
 
@@ -1685,7 +2221,7 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item,
 
   selected_frame_seen = FALSE;
 
-  for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
+  for (fdata = cf->plist_start; fdata != NULL; fdata = fdata->next) {
     /* Create the progress bar if necessary.
        We check on every iteration of the loop, so that it takes no
        longer than the standard time to create it (otherwise, for a
@@ -1721,15 +2257,15 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item,
       /* Well, the user decided to abort the filtering.  Just stop.
 
          XXX - go back to the previous filter?  Users probably just
-        want not to wait for a filtering operation to finish;
-        unless we cancel by having no filter, reverting to the
-        previous filter will probably be even more expensive than
-        continuing the filtering, as it involves going back to the
-        beginning and filtering, and even with no filter we currently
-        have to re-generate the entire clist, which is also expensive.
-
-        I'm not sure what Network Monitor does, but it doesn't appear
-        to give you an unfiltered display if you cancel. */
+     want not to wait for a filtering operation to finish;
+     unless we cancel by having no filter, reverting to the
+     previous filter will probably be even more expensive than
+     continuing the filtering, as it involves going back to the
+     beginning and filtering, and even with no filter we currently
+     have to re-generate the entire clist, which is also expensive.
+
+     I'm not sure what Network Monitor does, but it doesn't appear
+     to give you an unfiltered display if you cancel. */
       break;
     }
 
@@ -1739,20 +2275,14 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item,
       /* 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_dissection()"), 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->pfd = NULL;
-      }
+      frame_data_cleanup(fdata);
     }
 
-    if (!wtap_seek_read (cf->wth, fdata->file_off, &cf->pseudo_header,
-       cf->pd, fdata->cap_len, &err, &err_info)) {
-                       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
-                   cf_read_error_message(err, err_info), cf->filename);
-                       break;
-    }
+    if (!cf_read_frame(cf, fdata))
+      break; /* error reading the frame */
 
     /* If the previous frame is displayed, and we haven't yet seen the
        selected frame, remember that frame - it's the closest one we've
@@ -1763,7 +2293,8 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item,
     }
     row = add_packet_to_packet_list(fdata, cf, dfcode, filtering_tap_listeners,
                                     tap_flags, &cf->pseudo_header, cf->pd,
-                                    refilter);
+                                    refilter,
+                                    add_to_packet_list);
 
     /* If this frame is displayed, and this is the first frame we've
        seen displayed after the selected frame, remember this frame -
@@ -1787,11 +2318,6 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item,
   /* We are done redissecting the packet list. */
   cf->redissecting = FALSE;
 
-#ifndef NEW_PACKET_LIST
-  /* Re-sort the list using the previously selected order */
-  packet_list_set_sort_column();
-#endif
-
   if (redissect) {
     /* Clear out what remains of the visited flags and per-frame data
        pointers.
@@ -1804,10 +2330,7 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item,
        until it finishes.  Should we just stick them with that? */
     for (; fdata != NULL; fdata = fdata->next) {
       fdata->flags.visited = 0;
-      if (fdata->pfd) {
-               g_slist_free(fdata->pfd);
-        fdata->pfd = NULL;
-      }
+      frame_data_cleanup(fdata);
     }
   }
 
@@ -1817,11 +2340,7 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item,
     destroy_progress_dlg(progbar);
 
   /* Unfreeze the packet list. */
-#ifdef NEW_PACKET_LIST
-  new_packet_list_thaw();
-#else
   packet_list_thaw();
-#endif
 
   if (selected_row == -1) {
     /* The selected frame didn't pass the filter. */
@@ -1850,7 +2369,7 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item,
         selected_row = following_row;
       } else {
         /* Frames before and after the selected frame passed the filter, so
-                  we'll select the previous frame */
+           we'll select the previous frame */
         selected_row = preceding_row;
       }
     }
@@ -1860,7 +2379,6 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item,
     /* There are no frames displayed at all. */
     cf_unselect_packet(cf);
   } else {
-#ifndef NEW_PACKET_LIST
     /* Either the frame that was selected passed the filter, or we've
        found the nearest displayed frame to that frame.  Select it, make
        it the focus row, and make it visible. */
@@ -1869,14 +2387,92 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item,
       cf->current_row = -1;
     }
     packet_list_set_selected_row(selected_row);
-#endif /* NEW_PACKET_LIST */
   }
 
   /* Cleanup and release all dfilter resources */
-  if (dfcode != NULL){
-    dfilter_free(dfcode);
+  dfilter_free(dfcode);
+}
+#endif /* NEW_PACKET_LIST */
+
+/*
+ * Scan trough all frame data and recalculate the ref time
+ * without rereading the file.
+ * XXX - do we need a progres bar or is this fast enough?
+ */
+#ifdef NEW_PACKET_LIST
+static void
+ref_time_packets(capture_file *cf)
+{
+  frame_data *fdata;
+
+  nstime_set_unset(&first_ts);
+  nstime_set_unset(&prev_dis_ts);
+  cum_bytes = 0;
+
+  for (fdata = cf->plist_start; fdata != NULL; fdata = fdata->next) {
+    /* just add some value here until we know if it is being displayed or not */
+    fdata->cum_bytes = cum_bytes + fdata->pkt_len;
+
+    /*
+     *Timestamps
+     */
+
+    /* If we don't have the time stamp of the first packet in the
+     capture, it's because this is the first packet.  Save the time
+     stamp of this packet as the time stamp of the first packet. */
+    if (nstime_is_unset(&first_ts)) {
+        first_ts  = fdata->abs_ts;
+    }
+      /* if this frames is marked as a reference time frame, reset
+        firstsec and firstusec to this frame */
+    if(fdata->flags.ref_time){
+        first_ts = fdata->abs_ts;
+    }
+
+    /* If we don't have the time stamp of the previous displayed packet,
+     it's because this is the first displayed packet.  Save the time
+     stamp of this packet as the time stamp of the previous displayed
+     packet. */
+    if (nstime_is_unset(&prev_dis_ts)) {
+        prev_dis_ts = fdata->abs_ts;
+    }
+
+    /* Get the time elapsed between the first packet and this packet. */
+    nstime_delta(&fdata->rel_ts, &fdata->abs_ts, &first_ts);
+
+    /* 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 ((gint32)cf->elapsed_time.secs < fdata->rel_ts.secs
+        || ((gint32)cf->elapsed_time.secs == fdata->rel_ts.secs && (gint32)cf->elapsed_time.nsecs < fdata->rel_ts.nsecs)) {
+        cf->elapsed_time = fdata->rel_ts;
+    }
+
+    /* Get the time elapsed between the previous displayed packet and
+     this packet. */
+    nstime_delta(&fdata->del_dis_ts, &fdata->abs_ts, &prev_dis_ts);
+
+    prev_dis_ts = fdata->abs_ts;
+
+    /*
+     * Byte counts
+     */
+    if( (fdata->flags.passed_dfilter) || (fdata->flags.ref_time) ){
+        /* This frame either passed the display filter list or is marked as
+        a time reference frame.  All time reference frames are displayed
+        even if they dont pass the display filter */
+        if(fdata->flags.ref_time){
+            /* if this was a TIME REF frame we should reset the cum_bytes field */
+            cum_bytes = fdata->pkt_len;
+            fdata->cum_bytes =  cum_bytes;
+        } else {
+            /* increase cum_bytes with this packets length */
+            cum_bytes += fdata->pkt_len;
+        }
+    }
   }
 }
+#endif
 
 typedef enum {
   PSP_FINISHED,
@@ -1892,8 +2488,6 @@ process_specified_packets(capture_file *cf, packet_range_t *range,
     void *callback_args)
 {
   frame_data *fdata;
-  int         err;
-  gchar      *err_info;
   union wtap_pseudo_header pseudo_header;
   guint8      pd[WTAP_MAX_PACKET_SIZE+1];
   psp_return_t ret = PSP_FINISHED;
@@ -1925,7 +2519,7 @@ process_specified_packets(capture_file *cf, packet_range_t *range,
 
   /* Iterate through the list of packets, printing the packets that
      were selected by the current display filter.  */
-  for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
+  for (fdata = cf->plist_start; fdata != NULL; fdata = fdata->next) {
     /* Create the progress bar if necessary.
        We check on every iteration of the loop, so that it takes no
        longer than the standard time to create it (otherwise, for a
@@ -1980,11 +2574,8 @@ process_specified_packets(capture_file *cf, packet_range_t *range,
     }
 
     /* Get the packet */
-    if (!wtap_seek_read(cf->wth, fdata->file_off, &pseudo_header,
-                        pd, fdata->cap_len, &err, &err_info)) {
+    if (!cf_read_frame_r(cf, fdata, &pseudo_header, pd)) {
       /* Attempt to get the packet failed. */
-      simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
-                    cf_read_error_message(err, err_info), cf->filename);
       ret = PSP_FAILED;
       break;
     }
@@ -2015,13 +2606,13 @@ retap_packet(capture_file *cf _U_, frame_data *fdata,
              void *argsp)
 {
   retap_callback_args_t *args = argsp;
-  epan_dissect_t *edt;
+  epan_dissect_t edt;
 
-  edt = epan_dissect_new(args->construct_protocol_tree, FALSE);
-  tap_queue_init(edt);
-  epan_dissect_run(edt, pseudo_header, pd, fdata, args->cinfo);
-  tap_push_tapped_queue(edt);
-  epan_dissect_free(edt);
+  epan_dissect_init(&edt, args->construct_protocol_tree, FALSE);
+  tap_queue_init(&edt);
+  epan_dissect_run(&edt, pseudo_header, pd, fdata, args->cinfo);
+  tap_push_tapped_queue(&edt);
+  epan_dissect_cleanup(&edt);
 
   return TRUE;
 }
@@ -2093,30 +2684,31 @@ print_packet(capture_file *cf, frame_data *fdata,
              void *argsp)
 {
   print_callback_args_t *args = argsp;
-  epan_dissect_t *edt;
+  epan_dissect_t edt;
   int             i;
   char           *cp;
   int             line_len;
   int             column_len;
   int             cp_off;
   gboolean        proto_tree_needed;
-  char            bookmark_name[9+10+1];       /* "__frameNNNNNNNNNN__\0" */
-  char            bookmark_title[6+10+1];      /* "Frame NNNNNNNNNN__\0" */
+  char            bookmark_name[9+10+1];    /* "__frameNNNNNNNNNN__\0" */
+  char            bookmark_title[6+10+1];   /* "Frame NNNNNNNNNN__\0" */
 
   /* Create the protocol tree, and make it visible, if we're printing
      the dissection or the hex data.
      XXX - do we need it if we're just printing the hex data? */
   proto_tree_needed =
       args->print_args->print_dissections != print_dissections_none || args->print_args->print_hex || have_custom_cols(&cf->cinfo);
-  edt = epan_dissect_new(proto_tree_needed, proto_tree_needed);
+  epan_dissect_init(&edt, proto_tree_needed, proto_tree_needed);
 
   /* Fill in the column information if we're printing the summary
      information. */
   if (args->print_args->print_summary) {
-    epan_dissect_run(edt, pseudo_header, pd, fdata, &cf->cinfo);
-    epan_dissect_fill_in_columns(edt);
+    col_custom_prime_edt(&edt, &cf->cinfo);
+    epan_dissect_run(&edt, pseudo_header, pd, fdata, &cf->cinfo);
+    epan_dissect_fill_in_columns(&edt, FALSE, TRUE);
   } else
-    epan_dissect_run(edt, pseudo_header, pd, fdata, NULL);
+    epan_dissect_run(&edt, pseudo_header, pd, fdata, NULL);
 
   if (args->print_formfeed) {
     if (!new_page(args->print_args->stream))
@@ -2138,7 +2730,7 @@ print_packet(capture_file *cf, frame_data *fdata,
     if (args->print_header_line) {
       if (!print_line(args->print_args->stream, 0, args->header_line_buf))
         goto fail;
-      args->print_header_line = FALSE; /* we might not need to print any more */
+      args->print_header_line = FALSE;  /* we might not need to print any more */
     }
     cp = &args->line_buf[0];
     line_len = 0;
@@ -2150,7 +2742,7 @@ print_packet(capture_file *cf, frame_data *fdata,
 
       /* 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 */
+      line_len += column_len + 1;   /* "+1" for space */
       if (line_len > args->line_buf_len) {
         cp_off = (int) (cp - args->line_buf);
         args->line_buf_len = 2 * line_len;
@@ -2197,7 +2789,7 @@ print_packet(capture_file *cf, frame_data *fdata,
     }
 
     /* Print the information in that tree. */
-    if (!proto_tree_print(args->print_args, edt, args->print_args->stream))
+    if (!proto_tree_print(args->print_args, &edt, args->print_args->stream))
       goto fail;
 
     /* Print a blank line if we print anything after this (aka more than one packet). */
@@ -2209,7 +2801,7 @@ print_packet(capture_file *cf, frame_data *fdata,
 
   if (args->print_args->print_hex) {
     /* Print the full packet data as hex. */
-    if (!print_hex_data(args->print_args->stream, edt))
+    if (!print_hex_data(args->print_args->stream, &edt))
       goto fail;
 
     /* Print a blank line if we print anything after this (aka more than one packet). */
@@ -2219,7 +2811,7 @@ print_packet(capture_file *cf, frame_data *fdata,
     args->print_header_line = TRUE;
   } /* if (args->print_args->print_dissections != print_dissections_none) */
 
-  epan_dissect_free(edt);
+  epan_dissect_cleanup(&edt);
 
   /* do we want to have a formfeed between each packet from now on? */
   if(args->print_args->print_formfeed) {
@@ -2229,7 +2821,7 @@ print_packet(capture_file *cf, frame_data *fdata,
   return TRUE;
 
 fail:
-  epan_dissect_free(edt);
+  epan_dissect_cleanup(&edt);
   return FALSE;
 }
 
@@ -2289,7 +2881,7 @@ cf_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. */
-      line_len += column_len + 1;      /* "+1" for space */
+      line_len += column_len + 1;   /* "+1" for space */
       if (line_len > callback_args.header_line_buf_len) {
         cp_off = (int) (cp - callback_args.header_line_buf);
         callback_args.header_line_buf_len = 2 * line_len;
@@ -2365,19 +2957,19 @@ cf_print_packets(capture_file *cf, print_args_t *print_args)
 static gboolean
 write_pdml_packet(capture_file *cf _U_, frame_data *fdata,
                   union wtap_pseudo_header *pseudo_header, const guint8 *pd,
-                 void *argsp)
+          void *argsp)
 {
   FILE *fh = argsp;
-  epan_dissect_t *edt;
+  epan_dissect_t edt;
 
   /* Create the protocol tree, but don't fill in the column information. */
-  edt = epan_dissect_new(TRUE, TRUE);
-  epan_dissect_run(edt, pseudo_header, pd, fdata, NULL);
+  epan_dissect_init(&edt, TRUE, TRUE);
+  epan_dissect_run(&edt, pseudo_header, pd, fdata, NULL);
 
   /* Write out the information in that tree. */
-  proto_tree_write_pdml(edt, fh);
+  proto_tree_write_pdml(&edt, fh);
 
-  epan_dissect_free(edt);
+  epan_dissect_cleanup(&edt);
 
   return !ferror(fh);
 }
@@ -2390,7 +2982,7 @@ cf_write_pdml_packets(capture_file *cf, print_args_t *print_args)
 
   fh = ws_fopen(print_args->file, "w");
   if (fh == NULL)
-    return CF_PRINT_OPEN_ERROR;        /* attempt to open destination failed */
+    return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
 
   write_pdml_preamble(fh);
   if (ferror(fh)) {
@@ -2435,23 +3027,24 @@ cf_write_pdml_packets(capture_file *cf, print_args_t *print_args)
 static gboolean
 write_psml_packet(capture_file *cf, frame_data *fdata,
                   union wtap_pseudo_header *pseudo_header, const guint8 *pd,
-                 void *argsp)
+          void *argsp)
 {
   FILE *fh = argsp;
-  epan_dissect_t *edt;
+  epan_dissect_t edt;
   gboolean proto_tree_needed;
 
   /* Fill in the column information, only create the protocol tree
      if having custom columns. */
   proto_tree_needed = have_custom_cols(&cf->cinfo);
-  edt = epan_dissect_new(proto_tree_needed, proto_tree_needed);
-  epan_dissect_run(edt, pseudo_header, pd, fdata, &cf->cinfo);
-  epan_dissect_fill_in_columns(edt);
+  epan_dissect_init(&edt, proto_tree_needed, proto_tree_needed);
+  col_custom_prime_edt(&edt, &cf->cinfo);
+  epan_dissect_run(&edt, pseudo_header, pd, fdata, &cf->cinfo);
+  epan_dissect_fill_in_columns(&edt, FALSE, TRUE);
 
   /* Write out the information in that tree. */
-  proto_tree_write_psml(edt, fh);
+  proto_tree_write_psml(&edt, fh);
 
-  epan_dissect_free(edt);
+  epan_dissect_cleanup(&edt);
 
   return !ferror(fh);
 }
@@ -2464,7 +3057,7 @@ cf_write_psml_packets(capture_file *cf, print_args_t *print_args)
 
   fh = ws_fopen(print_args->file, "w");
   if (fh == NULL)
-    return CF_PRINT_OPEN_ERROR;        /* attempt to open destination failed */
+    return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
 
   write_psml_preamble(fh);
   if (ferror(fh)) {
@@ -2512,20 +3105,21 @@ write_csv_packet(capture_file *cf, frame_data *fdata,
                  void *argsp)
 {
   FILE *fh = argsp;
-  epan_dissect_t *edt;
+  epan_dissect_t edt;
   gboolean proto_tree_needed;
 
   /* Fill in the column information, only create the protocol tree
      if having custom columns. */
   proto_tree_needed = have_custom_cols(&cf->cinfo);
-  edt = epan_dissect_new(proto_tree_needed, proto_tree_needed);
-  epan_dissect_run(edt, pseudo_header, pd, fdata, &cf->cinfo);
-  epan_dissect_fill_in_columns(edt);
+  epan_dissect_init(&edt, proto_tree_needed, proto_tree_needed);
+  col_custom_prime_edt(&edt, &cf->cinfo);
+  epan_dissect_run(&edt, pseudo_header, pd, fdata, &cf->cinfo);
+  epan_dissect_fill_in_columns(&edt, FALSE, TRUE);
 
   /* Write out the information in that tree. */
-  proto_tree_write_csv(edt, fh);
+  proto_tree_write_csv(&edt, fh);
 
-  epan_dissect_free(edt);
+  epan_dissect_cleanup(&edt);
 
   return !ferror(fh);
 }
@@ -2582,8 +3176,8 @@ cf_write_csv_packets(capture_file *cf, print_args_t *print_args)
 
 static gboolean
 write_carrays_packet(capture_file *cf _U_, frame_data *fdata,
-                    union wtap_pseudo_header *pseudo_header _U_,
-                    const guint8 *pd, void *argsp)
+             union wtap_pseudo_header *pseudo_header _U_,
+             const guint8 *pd, void *argsp)
 {
   FILE *fh = argsp;
 
@@ -2612,8 +3206,8 @@ cf_write_carrays_packets(capture_file *cf, print_args_t *print_args)
   /* Iterate through the list of packets, printing the packets we were
      told to print. */
   ret = process_specified_packets(cf, &print_args->range,
-                                 "Writing C Arrays",
-                                 "selected packets", TRUE,
+                  "Writing C Arrays",
+                  "selected packets", TRUE,
                                   write_carrays_packet, fh);
   switch (ret) {
   case PSP_FINISHED:
@@ -2639,18 +3233,20 @@ cf_write_carrays_packets(capture_file *cf, print_args_t *print_args)
   return CF_PRINT_OK;
 }
 
+#ifndef NEW_PACKET_LIST /* This function is not needed with the new packet list */
+
 /* Scan through the packet list and change all columns that use the
    "command-line-specified" time stamp format to use the current
    value of that format. */
 void
 cf_change_time_formats(capture_file *cf)
 {
+  int         i;
   frame_data *fdata;
   progdlg_t  *progbar = NULL;
   gboolean    stop_flag;
   int         count;
   int         row;
-  int         i;
   float       progbar_val;
   GTimeVal    start_time;
   gchar       status_str[100];
@@ -2658,8 +3254,7 @@ cf_change_time_formats(capture_file *cf)
   int         progbar_quantum;
   gboolean    sorted_by_frame_column;
 
-
-  /* adjust timestamp precision if auto is selected */
+  /* Adjust timestamp precision if auto is selected */
   cf_timestamp_auto_precision(cf);
 
   /* Are there any columns with time stamps in the "command-line-specified"
@@ -2681,11 +3276,7 @@ cf_change_time_formats(capture_file *cf)
 
   /* Freeze the packet list while we redo it, so we don't get any
      screen updates while it happens. */
-#ifdef NEW_PACKET_LIST
-  new_packet_list_freeze();
-#else
   packet_list_freeze();
-#endif
 
   /* Update the progress bar when it gets to this value. */
   progbar_nextstep = 0;
@@ -2713,9 +3304,7 @@ cf_change_time_formats(capture_file *cf)
   for (i = 0; i < cf->cinfo.num_cols; i++) {
     if (cf->cinfo.col_fmt[i] == COL_NUMBER)
     {
-#ifndef NEW_PACKET_LIST
       sorted_by_frame_column = (i == packet_list_get_sort_column());
-#endif
       break;
     }
   }
@@ -2727,7 +3316,7 @@ cf_change_time_formats(capture_file *cf)
      is in a row of the summary list and, if so, whether there are
      any columns that show the time in the "command-line-specified"
      format and, if so, update that row. */
-  for (fdata = cf->plist, row = -1; fdata != NULL; fdata = fdata->next) {
+  for (fdata = cf->plist_start, row = -1; fdata != NULL; fdata = fdata->next) {
     /* Create the progress bar if necessary.
        We check on every iteration of the loop, so that it takes no
        longer than the standard time to create it (otherwise, for a
@@ -2763,8 +3352,8 @@ cf_change_time_formats(capture_file *cf)
       /* Well, the user decided to abort the redisplay.  Just stop.
 
          XXX - this leaves the time field in the old format in
-        frames we haven't yet processed.  So it goes; should we
-        simply not offer them the option of stopping? */
+     frames we haven't yet processed.  So it goes; should we
+     simply not offer them the option of stopping? */
       break;
     }
 
@@ -2773,11 +3362,7 @@ cf_change_time_formats(capture_file *cf)
     /* Find what row this packet is in. */
     if (!sorted_by_frame_column) {
       /* This function is O(N), so we try to avoid using it... */
-#ifdef NEW_PACKET_LIST
-         row = new_packet_list_find_row_from_data(fdata, FALSE);
-#else
       row = packet_list_find_row_from_data(fdata);
-#endif
     } else {
       /* ...which we do by maintaining a count of packets that are
          being displayed (i.e., that have passed the display filter),
@@ -2785,9 +3370,9 @@ cf_change_time_formats(capture_file *cf)
          (which is why we can only do it when the display is sorted
          by the frame number). */
       if (fdata->flags.passed_dfilter)
-       row++;
+        row++;
       else
-       continue;
+        continue;
     }
 
     if (row != -1) {
@@ -2799,10 +3384,7 @@ cf_change_time_formats(capture_file *cf)
              "command-line-specified" format; update it. */
           cf->cinfo.col_buf[i][0] = '\0';
           col_set_fmt_time(fdata, &cf->cinfo, cf->cinfo.col_fmt[i], i);
-#ifdef NEW_PACKET_LIST
-#else
           packet_list_set_text(row, i, cf->cinfo.col_data[i]);
-#endif
         }
       }
     }
@@ -2817,70 +3399,75 @@ cf_change_time_formats(capture_file *cf)
      "command-line-specified" format. */
   for (i = 0; i < cf->cinfo.num_cols; i++) {
     if (col_has_time_fmt(&cf->cinfo, i)) {
-#ifndef NEW_PACKET_LIST
       packet_list_set_time_width(cf->cinfo.col_fmt[i], i);
-#endif
     }
   }
 
   /* Unfreeze the packet list. */
-#ifdef NEW_PACKET_LIST
-  new_packet_list_thaw();
-#else
   packet_list_thaw();
-#endif
 }
+#endif /* NEW_PACKET_LIST */
+
 
 typedef struct {
-       const char      *string;
-       size_t          string_len;
-       capture_file    *cf;
-       gboolean        frame_matched;
+    const char  *string;
+    size_t      string_len;
+    capture_file    *cf;
+    gboolean    frame_matched;
 } match_data;
 
 gboolean
-cf_find_packet_protocol_tree(capture_file *cf, const char *string)
+cf_find_packet_protocol_tree(capture_file *cf, const char *string,
+                             search_direction dir)
 {
-  match_data           mdata;
+  match_data        mdata;
 
   mdata.string = string;
   mdata.string_len = strlen(string);
-  return find_packet(cf, match_protocol_tree, &mdata);
+  return find_packet(cf, match_protocol_tree, &mdata, dir);
 }
 
-static gboolean
+static match_result
 match_protocol_tree(capture_file *cf, frame_data *fdata, void *criterion)
 {
-  match_data           *mdata = criterion;
-  epan_dissect_t       *edt;
+  match_data        *mdata = criterion;
+  epan_dissect_t    edt;
+
+  /* Load the frame's data. */
+  if (!cf_read_frame(cf, fdata)) {
+    /* Attempt to get the packet failed. */
+    return MR_ERROR;
+  }
 
   /* Construct the protocol tree, including the displayed text */
-  edt = epan_dissect_new(TRUE, TRUE);
+  epan_dissect_init(&edt, TRUE, TRUE);
   /* We don't need the column information */
-  epan_dissect_run(edt, &cf->pseudo_header, cf->pd, fdata, NULL);
+  epan_dissect_run(&edt, &cf->pseudo_header, cf->pd, fdata, NULL);
 
   /* Iterate through all the nodes, seeing if they have text that matches. */
   mdata->cf = cf;
   mdata->frame_matched = FALSE;
-  proto_tree_children_foreach(edt->tree, match_subtree_text, mdata);
-  epan_dissect_free(edt);
-  return mdata->frame_matched;
+  proto_tree_children_foreach(edt.tree, match_subtree_text, mdata);
+  epan_dissect_cleanup(&edt);
+  return mdata->frame_matched ? MR_MATCHED : MR_NOTMATCHED;
 }
 
 static void
 match_subtree_text(proto_node *node, gpointer data)
 {
-  match_data   *mdata = (match_data*) data;
-  const gchar  *string = mdata->string;
-  size_t       string_len = mdata->string_len;
-  capture_file *cf = mdata->cf;
-  field_info   *fi = PITEM_FINFO(node);
-  gchar                label_str[ITEM_LABEL_LENGTH];
-  gchar                *label_ptr;
-  size_t       label_len;
-  guint32      i;
-  guint8       c_char;
-  size_t       c_match = 0;
+  match_data    *mdata = (match_data*) data;
+  const gchar   *string = mdata->string;
+  size_t        string_len = mdata->string_len;
+  capture_file  *cf = mdata->cf;
+  field_info    *fi = PNODE_FINFO(node);
+  gchar         label_str[ITEM_LABEL_LENGTH];
+  gchar         *label_ptr;
+  size_t        label_len;
+  guint32       i;
+  guint8        c_char;
+  size_t        c_match = 0;
+
+  g_assert(fi && "dissection with an invisible proto tree?");
 
   if (mdata->frame_matched) {
     /* We already had a match; don't bother doing any more work. */
@@ -2909,9 +3496,9 @@ match_subtree_text(proto_node *node, gpointer data)
     if (c_char == string[c_match]) {
       c_match++;
       if (c_match == string_len) {
-       /* No need to look further; we have a match */
-       mdata->frame_matched = TRUE;
-       return;
+        /* No need to look further; we have a match */
+        mdata->frame_matched = TRUE;
+        return;
       }
     } else
       c_match = 0;
@@ -2923,68 +3510,76 @@ match_subtree_text(proto_node *node, gpointer data)
 }
 
 gboolean
-cf_find_packet_summary_line(capture_file *cf, const char *string)
+cf_find_packet_summary_line(capture_file *cf, const char *string,
+                            search_direction dir)
 {
-  match_data           mdata;
+  match_data        mdata;
 
   mdata.string = string;
   mdata.string_len = strlen(string);
-  return find_packet(cf, match_summary_line, &mdata);
+  return find_packet(cf, match_summary_line, &mdata, dir);
 }
 
-static gboolean
+static match_result
 match_summary_line(capture_file *cf, frame_data *fdata, void *criterion)
 {
-  match_data           *mdata = criterion;
-  const gchar          *string = mdata->string;
-  size_t               string_len = mdata->string_len;
-  epan_dissect_t       *edt;
-  const char           *info_column;
-  size_t               info_column_len;
-  gboolean             frame_matched = FALSE;
-  gint                 colx;
-  guint32              i;
-  guint8               c_char;
-  size_t               c_match = 0;
+  match_data        *mdata = criterion;
+  const gchar       *string = mdata->string;
+  size_t            string_len = mdata->string_len;
+  epan_dissect_t    edt;
+  const char        *info_column;
+  size_t            info_column_len;
+  match_result      result = MR_NOTMATCHED;
+  gint              colx;
+  guint32           i;
+  guint8            c_char;
+  size_t            c_match = 0;
+
+  /* Load the frame's data. */
+  if (!cf_read_frame(cf, fdata)) {
+    /* Attempt to get the packet failed. */
+    return MR_ERROR;
+  }
 
   /* Don't bother constructing the protocol tree */
-  edt = epan_dissect_new(FALSE, FALSE);
+  epan_dissect_init(&edt, FALSE, FALSE);
   /* Get the column information */
-  epan_dissect_run(edt, &cf->pseudo_header, cf->pd, fdata, &cf->cinfo);
+  epan_dissect_run(&edt, &cf->pseudo_header, cf->pd, fdata, &cf->cinfo);
 
   /* Find the Info column */
   for (colx = 0; colx < cf->cinfo.num_cols; colx++) {
     if (cf->cinfo.fmt_matx[colx][COL_INFO]) {
       /* Found it.  See if we match. */
-      info_column = edt->pi.cinfo->col_data[colx];
+      info_column = edt.pi.cinfo->col_data[colx];
       info_column_len = strlen(info_column);
       for (i = 0; i < info_column_len; i++) {
-       c_char = info_column[i];
-       if (cf->case_type)
-         c_char = toupper(c_char);
-       if (c_char == string[c_match]) {
-         c_match++;
-         if (c_match == string_len) {
-           frame_matched = TRUE;
-           break;
-         }
-       } else
-         c_match = 0;
+        c_char = info_column[i];
+        if (cf->case_type)
+          c_char = toupper(c_char);
+        if (c_char == string[c_match]) {
+          c_match++;
+          if (c_match == string_len) {
+            result = MR_MATCHED;
+            break;
+          }
+        } else
+          c_match = 0;
       }
       break;
     }
   }
-  epan_dissect_free(edt);
-  return frame_matched;
+  epan_dissect_cleanup(&edt);
+  return result;
 }
 
 typedef struct {
-       const guint8 *data;
-       size_t data_len;
-} cbs_t;       /* "Counted byte string" */
+    const guint8 *data;
+    size_t data_len;
+} cbs_t;    /* "Counted byte string" */
 
 gboolean
-cf_find_packet_data(capture_file *cf, const guint8 *string, size_t string_size)
+cf_find_packet_data(capture_file *cf, const guint8 *string, size_t string_size,
+                    search_direction dir)
 {
   cbs_t info;
 
@@ -2997,35 +3592,41 @@ cf_find_packet_data(capture_file *cf, const guint8 *string, size_t string_size)
     switch (cf->scs_type) {
 
     case SCS_ASCII_AND_UNICODE:
-      return find_packet(cf, match_ascii_and_unicode, &info);
+      return find_packet(cf, match_ascii_and_unicode, &info, dir);
 
     case SCS_ASCII:
-      return find_packet(cf, match_ascii, &info);
+      return find_packet(cf, match_ascii, &info, dir);
 
     case SCS_UNICODE:
-      return find_packet(cf, match_unicode, &info);
+      return find_packet(cf, match_unicode, &info, dir);
 
     default:
       g_assert_not_reached();
       return FALSE;
     }
   } else
-    return find_packet(cf, match_binary, &info);
+    return find_packet(cf, match_binary, &info, dir);
 }
 
-static gboolean
+static match_result
 match_ascii_and_unicode(capture_file *cf, frame_data *fdata, void *criterion)
 {
-  cbs_t                *info = criterion;
-  const guint8 *ascii_text = info->data;
-  size_t       textlen = info->data_len;
-  gboolean     frame_matched;
-  guint32      buf_len;
-  guint32      i;
-  guint8       c_char;
-  size_t       c_match = 0;
-
-  frame_matched = FALSE;
+  cbs_t        *info = criterion;
+  const guint8 *ascii_text = info->data;
+  size_t       textlen = info->data_len;
+  match_result result;
+  guint32      buf_len;
+  guint32      i;
+  guint8       c_char;
+  size_t       c_match = 0;
+
+  /* Load the frame's data. */
+  if (!cf_read_frame(cf, fdata)) {
+    /* Attempt to get the packet failed. */
+    return MR_ERROR;
+  }
+
+  result = MR_NOTMATCHED;
   buf_len = fdata->pkt_len;
   for (i = 0; i < buf_len; i++) {
     c_char = cf->pd[i];
@@ -3033,33 +3634,39 @@ match_ascii_and_unicode(capture_file *cf, frame_data *fdata, void *criterion)
       c_char = toupper(c_char);
     if (c_char != 0) {
       if (c_char == ascii_text[c_match]) {
-       c_match++;
-       if (c_match == textlen) {
-         frame_matched = TRUE;
-         cf->search_pos = i; /* Save the position of the last character
-                              for highlighting the field. */
-         break;
-       }
+        c_match++;
+        if (c_match == textlen) {
+          result = MR_MATCHED;
+          cf->search_pos = i; /* Save the position of the last character
+                                 for highlighting the field. */
+          break;
+        }
       } else
-       c_match = 0;
+        c_match = 0;
     }
   }
-  return frame_matched;
+  return result;
 }
 
-static gboolean
+static match_result
 match_ascii(capture_file *cf, frame_data *fdata, void *criterion)
 {
-  cbs_t                *info = criterion;
-  const guint8 *ascii_text = info->data;
-  size_t       textlen = info->data_len;
-  gboolean     frame_matched;
-  guint32      buf_len;
-  guint32      i;
-  guint8       c_char;
-  size_t       c_match = 0;
-
-  frame_matched = FALSE;
+  cbs_t        *info = criterion;
+  const guint8 *ascii_text = info->data;
+  size_t       textlen = info->data_len;
+  match_result result;
+  guint32      buf_len;
+  guint32      i;
+  guint8       c_char;
+  size_t       c_match = 0;
+
+  /* Load the frame's data. */
+  if (!cf_read_frame(cf, fdata)) {
+    /* Attempt to get the packet failed. */
+    return MR_ERROR;
+  }
+
+  result = MR_NOTMATCHED;
   buf_len = fdata->pkt_len;
   for (i = 0; i < buf_len; i++) {
     c_char = cf->pd[i];
@@ -3068,30 +3675,36 @@ match_ascii(capture_file *cf, frame_data *fdata, void *criterion)
     if (c_char == ascii_text[c_match]) {
       c_match++;
       if (c_match == textlen) {
-       frame_matched = TRUE;
-       cf->search_pos = i; /* Save the position of the last character
-                              for highlighting the field. */
-       break;
+        result = MR_MATCHED;
+        cf->search_pos = i; /* Save the position of the last character
+                               for highlighting the field. */
+        break;
       }
     } else
       c_match = 0;
   }
-  return frame_matched;
+  return result;
 }
 
-static gboolean
+static match_result
 match_unicode(capture_file *cf, frame_data *fdata, void *criterion)
 {
-  cbs_t                *info = criterion;
-  const guint8 *ascii_text = info->data;
-  size_t       textlen = info->data_len;
-  gboolean     frame_matched;
-  guint32      buf_len;
-  guint32      i;
-  guint8       c_char;
-  size_t       c_match = 0;
-
-  frame_matched = FALSE;
+  cbs_t        *info = criterion;
+  const guint8 *ascii_text = info->data;
+  size_t       textlen = info->data_len;
+  match_result result;
+  guint32      buf_len;
+  guint32      i;
+  guint8       c_char;
+  size_t       c_match = 0;
+
+  /* Load the frame's data. */
+  if (!cf_read_frame(cf, fdata)) {
+    /* Attempt to get the packet failed. */
+    return MR_ERROR;
+  }
+
+  result = MR_NOTMATCHED;
   buf_len = fdata->pkt_len;
   for (i = 0; i < buf_len; i++) {
     c_char = cf->pd[i];
@@ -3101,86 +3714,148 @@ match_unicode(capture_file *cf, frame_data *fdata, void *criterion)
       c_match++;
       i++;
       if (c_match == textlen) {
-       frame_matched = TRUE;
-       cf->search_pos = i; /* Save the position of the last character
-                              for highlighting the field. */
-       break;
+        result = MR_MATCHED;
+        cf->search_pos = i; /* Save the position of the last character
+                               for highlighting the field. */
+        break;
       }
     } else
       c_match = 0;
   }
-  return frame_matched;
+  return result;
 }
 
-static gboolean
+static match_result
 match_binary(capture_file *cf, frame_data *fdata, void *criterion)
 {
-  cbs_t                *info = criterion;
-  const guint8 *binary_data = info->data;
-  size_t       datalen = info->data_len;
-  gboolean     frame_matched;
-  guint32      buf_len;
-  guint32      i;
-  size_t       c_match = 0;
-
-  frame_matched = FALSE;
+  cbs_t        *info = criterion;
+  const guint8 *binary_data = info->data;
+  size_t       datalen = info->data_len;
+  match_result result;
+  guint32      buf_len;
+  guint32      i;
+  size_t       c_match = 0;
+
+  /* Load the frame's data. */
+  if (!cf_read_frame(cf, fdata)) {
+    /* Attempt to get the packet failed. */
+    return MR_ERROR;
+  }
+
+  result = MR_NOTMATCHED;
   buf_len = fdata->pkt_len;
   for (i = 0; i < buf_len; i++) {
     if (cf->pd[i] == binary_data[c_match]) {
       c_match++;
       if (c_match == datalen) {
-       frame_matched = TRUE;
-       cf->search_pos = i; /* Save the position of the last character
-                              for highlighting the field. */
-       break;
+        result = MR_MATCHED;
+        cf->search_pos = i; /* Save the position of the last character
+                               for highlighting the field. */
+        break;
       }
     } else
       c_match = 0;
   }
-  return frame_matched;
+  return result;
 }
 
 gboolean
-cf_find_packet_dfilter(capture_file *cf, dfilter_t *sfcode)
+cf_find_packet_dfilter(capture_file *cf, dfilter_t *sfcode,
+                       search_direction dir)
 {
-  return find_packet(cf, match_dfilter, sfcode);
+  return find_packet(cf, match_dfilter, sfcode, dir);
 }
 
-static gboolean
+gboolean
+cf_find_packet_dfilter_string(capture_file *cf, const char *filter,
+                              search_direction dir)
+{
+  dfilter_t *sfcode;
+  gboolean result;
+
+  if (!dfilter_compile(filter, &sfcode)) {
+     /*
+      * XXX - this shouldn't happen, as the filter string is machine
+      * generated
+      */
+    return FALSE;
+  }
+  if (sfcode == NULL) {
+    /*
+     * XXX - this shouldn't happen, as the filter string is machine
+     * generated.
+     */
+    return FALSE;
+  }
+  result = find_packet(cf, match_dfilter, sfcode, dir);
+  dfilter_free(sfcode);
+  return result;
+}
+
+static match_result
 match_dfilter(capture_file *cf, frame_data *fdata, void *criterion)
 {
-  dfilter_t            *sfcode = criterion;
-  epan_dissect_t       *edt;
-  gboolean             frame_matched;
-
-  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);
-  return frame_matched;
+  dfilter_t      *sfcode = criterion;
+  epan_dissect_t edt;
+  match_result   result;
+
+  /* Load the frame's data. */
+  if (!cf_read_frame(cf, fdata)) {
+    /* Attempt to get the packet failed. */
+    return MR_ERROR;
+  }
+
+  epan_dissect_init(&edt, TRUE, FALSE);
+  epan_dissect_prime_dfilter(&edt, sfcode);
+  epan_dissect_run(&edt, &cf->pseudo_header, cf->pd, fdata, NULL);
+  result = dfilter_apply_edt(sfcode, &edt) ? MR_MATCHED : MR_NOTMATCHED;
+  epan_dissect_cleanup(&edt);
+  return result;
+}
+
+gboolean
+cf_find_packet_marked(capture_file *cf, search_direction dir)
+{
+  return find_packet(cf, match_marked, NULL, dir);
+}
+
+static match_result
+match_marked(capture_file *cf _U_, frame_data *fdata, void *criterion _U_)
+{
+  return fdata->flags.marked ? MR_MATCHED : MR_NOTMATCHED;
+}
+
+gboolean
+cf_find_packet_time_reference(capture_file *cf, search_direction dir)
+{
+  return find_packet(cf, match_time_reference, NULL, dir);
+}
+
+static match_result
+match_time_reference(capture_file *cf _U_, frame_data *fdata, void *criterion _U_)
+{
+  return fdata->flags.ref_time ? MR_MATCHED : MR_NOTMATCHED;
 }
 
 static gboolean
 find_packet(capture_file *cf,
-            gboolean (*match_function)(capture_file *, frame_data *, void *),
-            void *criterion)
+            match_result (*match_function)(capture_file *, frame_data *, void *),
+            void *criterion, search_direction dir)
 {
-  frame_data *start_fd;
-  frame_data *fdata;
-  frame_data *new_fd = NULL;
-  progdlg_t  *progbar = NULL;
-  gboolean    stop_flag;
-  int         count;
-  int         err;
-  gchar      *err_info;
-  int         row;
-  float       progbar_val;
-  GTimeVal    start_time;
-  gchar       status_str[100];
-  int         progbar_nextstep;
-  int         progbar_quantum;
-  char       *title;
+  frame_data  *start_fd;
+  frame_data  *fdata;
+  frame_data  *new_fd = NULL;
+  progdlg_t   *progbar = NULL;
+  gboolean     stop_flag;
+  int          count;
+  int          row;
+  float        progbar_val;
+  GTimeVal     start_time;
+  gchar        status_str[100];
+  int          progbar_nextstep;
+  int          progbar_quantum;
+  const char  *title;
+  match_result result;
 
   start_fd = cf->current_frame;
   if (start_fd != NULL)  {
@@ -3243,7 +3918,7 @@ find_packet(capture_file *cf,
       }
 
       /* Go past the current frame. */
-      if (cf->sbackward) {
+      if (dir == SD_BACKWARD) {
         /* Go on to the previous frame. */
         fdata = fdata->prev;
         if (fdata == NULL) {
@@ -3257,18 +3932,12 @@ find_packet(capture_file *cf,
 
           if (prefs.gui_find_wrap)
           {
-              simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
-                            "%sBeginning of capture exceeded!%s\n\n"
-                            "Search is continued from the end of the capture.",
-                            simple_dialog_primary_start(), simple_dialog_primary_end());
-              fdata = cf->plist_end;   /* wrap around */
+              statusbar_push_temporary_msg("Search reached the beginning. Continuing at end.");
+              fdata = cf->plist_end;    /* wrap around */
           }
           else
           {
-              simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
-                            "%sBeginning of capture exceeded!%s\n\n"
-                            "Try searching forwards.",
-                            simple_dialog_primary_start(), simple_dialog_primary_end());
+              statusbar_push_temporary_msg("Search reached the beginning.");
               fdata = start_fd;        /* stay on previous packet */
           }
         }
@@ -3278,18 +3947,12 @@ find_packet(capture_file *cf,
         if (fdata == NULL) {
           if (prefs.gui_find_wrap)
           {
-              simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
-                            "%sEnd of capture exceeded!%s\n\n"
-                            "Search is continued from the start of the capture.",
-                            simple_dialog_primary_start(), simple_dialog_primary_end());
-              fdata = cf->plist;       /* wrap around */
+              statusbar_push_temporary_msg("Search reached the end. Continuing at beginning.");
+              fdata = cf->plist_start;    /* wrap around */
           }
           else
           {
-              simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
-                            "%sEnd of capture exceeded!%s\n\n"
-                            "Try searching backwards.",
-                            simple_dialog_primary_start(), simple_dialog_primary_end());
+              statusbar_push_temporary_msg("Search reached the end.");
               fdata = start_fd;     /* stay on previous packet */
           }
         }
@@ -3299,27 +3962,23 @@ find_packet(capture_file *cf,
 
       /* Is this packet in the display? */
       if (fdata->flags.passed_dfilter) {
-       /* Yes.  Load its data. */
-        if (!wtap_seek_read(cf->wth, fdata->file_off, &cf->pseudo_header,
-                       cf->pd, fdata->cap_len, &err, &err_info)) {
-          /* Read error.  Report the error, and go back to the frame
+        /* Yes.  Does it match the search criterion? */
+        result = (*match_function)(cf, fdata, criterion);
+        if (result == MR_ERROR) {
+          /* Error; our caller has reported the error.  Go back to the frame
              where we started. */
-          simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
-                       cf_read_error_message(err, err_info), cf->filename);
           new_fd = start_fd;
           break;
-        }
-
-       /* Does it match the search criterion? */
-       if ((*match_function)(cf, fdata, criterion)) {
+        } else if (result == MR_MATCHED) {
+          /* Yes.  Go to the new frame. */
           new_fd = fdata;
-          break;       /* found it! */
+          break;
         }
       }
 
       if (fdata == start_fd) {
         /* We're back to the frame we were on originally, and that frame
-          doesn't match the search filter.  The search failed. */
+           doesn't match the search filter.  The search failed. */
         break;
       }
     }
@@ -3332,30 +3991,30 @@ find_packet(capture_file *cf,
 
   if (new_fd != NULL) {
 #ifdef NEW_PACKET_LIST
-         /* Find and select */
-         row = new_packet_list_find_row_from_data(fdata, TRUE);
+    /* Find and select */
+    row = new_packet_list_find_row_from_data(fdata, TRUE);
 #else
     /* We found a frame.  Find what row it's in. */
     row = packet_list_find_row_from_data(new_fd);
 #endif /* NEW_PACKET_LIST */
     if (row == -1) {
-        /* We didn't find a row even though we know that a frame
-         * exists that satifies the search criteria. This means that the
-         * frame isn't being displayed currently so we can't select it. */
-        simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
-                      "%sEnd of capture exceeded!%s\n\n"
-                      "The capture file is probably not fully loaded.",
-                      simple_dialog_primary_start(), simple_dialog_primary_end());
-        return FALSE;
+      /* We didn't find a row even though we know that a frame
+       * exists that satifies the search criteria. This means that the
+       * frame isn't being displayed currently so we can't select it. */
+      simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
+                    "%sEnd of capture exceeded!%s\n\n"
+                    "The capture file is probably not fully loaded.",
+                    simple_dialog_primary_start(), simple_dialog_primary_end());
+      return FALSE;
     }
 
 #ifndef NEW_PACKET_LIST
     /* Select that row, make it the focus row, and make it visible. */
     packet_list_set_selected_row(row);
 #endif /* NEW_PACKET_LIST */
-    return TRUE;       /* success */
+    return TRUE;    /* success */
   } else
-    return FALSE;      /* failure */
+    return FALSE;   /* failure */
 }
 
 gboolean
@@ -3364,21 +4023,19 @@ cf_goto_frame(capture_file *cf, guint fnumber)
   frame_data *fdata;
   int row;
 
-  for (fdata = cf->plist; fdata != NULL && fdata->num < fnumber; fdata = fdata->next)
+  for (fdata = cf->plist_start; fdata != NULL && fdata->num < fnumber; fdata = fdata->next)
     ;
 
   if (fdata == NULL) {
     /* we didn't find a packet with that packet number */
-    simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
-                 "There is no packet with the packet number %u.", fnumber);
-    return FALSE;      /* we failed to go to that packet */
+    statusbar_push_temporary_msg("There is no packet number %u.", fnumber);
+    return FALSE;   /* we failed to go to that packet */
   }
   if (!fdata->flags.passed_dfilter) {
     /* that packet currently isn't displayed */
     /* XXX - add it to the set of displayed packets? */
-    simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
-                 "The packet number %u isn't currently being displayed.", fnumber);
-    return FALSE;      /* we failed to go to that packet */
+    statusbar_push_temporary_msg("Packet number %u isn't displayed.", fnumber);
+    return FALSE;   /* we failed to go to that packet */
   }
 
 #ifdef NEW_PACKET_LIST
@@ -3392,11 +4049,11 @@ cf_goto_frame(capture_file *cf, guint fnumber)
   /* Select that row, make it the focus row, and make it visible. */
   packet_list_set_selected_row(row);
 #endif /* NEW_PACKET_LIST */
-  return TRUE; /* we got to that packet */
+  return TRUE;  /* we got to that packet */
 }
 
 gboolean
-cf_goto_top_frame(capture_file *cf)
+cf_goto_top_frame(capture_file *cf _U_)
 {
 #ifdef NEW_PACKET_LIST
   /* Find and select */
@@ -3406,7 +4063,7 @@ cf_goto_top_frame(capture_file *cf)
   int row;
   frame_data *lowest_fdata = NULL;
 
-  for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
+  for (fdata = cf->plist_start; fdata != NULL; fdata = fdata->next) {
     if (fdata->flags.passed_dfilter) {
         lowest_fdata = fdata;
         break;
@@ -3425,11 +4082,11 @@ cf_goto_top_frame(capture_file *cf)
   /* Select that row, make it the focus row, and make it visible. */
   packet_list_set_selected_row(row);
 #endif /* NEW_PACKET_LIST */
-  return TRUE; /* we got to that packet */
+  return TRUE;  /* we got to that packet */
 }
 
 gboolean
-cf_goto_bottom_frame(capture_file *cf)
+cf_goto_bottom_frame(capture_file *cf _U_) /* cf is unused w/ NEW_PACKET_LIST */
 {
 #ifdef NEW_PACKET_LIST
   /* Find and select */
@@ -3439,7 +4096,7 @@ cf_goto_bottom_frame(capture_file *cf)
   int row;
   frame_data *highest_fdata = NULL;
 
-  for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
+  for (fdata = cf->plist_start; fdata != NULL; fdata = fdata->next) {
     if (fdata->flags.passed_dfilter) {
         highest_fdata = fdata;
     }
@@ -3457,7 +4114,7 @@ cf_goto_bottom_frame(capture_file *cf)
   /* Select that row, make it the focus row, and make it visible. */
   packet_list_set_selected_row(row);
 #endif /* NEW_PACKET_LIST */
-  return TRUE; /* we got to that packet */
+  return TRUE;  /* we got to that packet */
 }
 
 /*
@@ -3487,8 +4144,6 @@ void
 cf_select_packet(capture_file *cf, int row)
 {
   frame_data *fdata;
-  int err;
-  gchar *err_info;
 
   /* Get the frame data struct pointer for this frame */
 #ifdef NEW_PACKET_LIST
@@ -3534,10 +4189,7 @@ cf_select_packet(capture_file *cf, int row)
   }
 
   /* Get the data in that frame. */
-  if (!wtap_seek_read (cf->wth, fdata->file_off, &cf->pseudo_header,
-                      cf->pd, fdata->cap_len, &err, &err_info)) {
-    simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
-                 cf_read_error_message(err, err_info), cf->filename);
+  if (!cf_read_frame (cf, fdata)) {
     return;
   }
 
@@ -3546,13 +4198,13 @@ cf_select_packet(capture_file *cf, int row)
   cf->current_row = row;
 
   /* Create the logical protocol tree. */
-  if (cf->edt != 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);
 
+  tap_build_interesting(cf->edt);
   epan_dissect_run(cf->edt, &cf->pseudo_header, cf->pd, cf->current_frame,
           NULL);
 
@@ -3616,6 +4268,32 @@ cf_unmark_frame(capture_file *cf, frame_data *frame)
   }
 }
 
+/*
+ * Ignore a particular frame.
+ */
+void
+cf_ignore_frame(capture_file *cf, frame_data *frame)
+{
+  if (! frame->flags.ignored) {
+    frame->flags.ignored = TRUE;
+    if (cf->count > cf->ignored_count)
+      cf->ignored_count++;
+  }
+}
+
+/*
+ * Un-ignore a particular frame.
+ */
+void
+cf_unignore_frame(capture_file *cf, frame_data *frame)
+{
+  if (frame->flags.ignored) {
+    frame->flags.ignored = FALSE;
+    if (cf->ignored_count > 0)
+      cf->ignored_count--;
+  }
+}
+
 typedef struct {
   wtap_dumper *pdh;
   const char  *fname;
@@ -3683,7 +4361,7 @@ cf_save(capture_file *cf, const char *fname, packet_range_t *range, guint save_f
   wtap_dumper  *pdh;
   save_callback_args_t callback_args;
 
-  cf_callback_invoke(cf_cb_file_safe_started, (gpointer) fname);
+  cf_callback_invoke(cf_cb_file_save_started, (gpointer)fname);
 
   /* don't write over an existing file. */
   /* this should've been already checked by our caller, just to be sure... */
@@ -3697,7 +4375,6 @@ cf_save(capture_file *cf, const char *fname, packet_range_t *range, guint save_f
 
   packet_range_process_init(range);
 
-
   if (packet_range_process_all(range) && 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. */
@@ -3705,30 +4382,30 @@ cf_save(capture_file *cf, const char *fname, packet_range_t *range, guint save_f
     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;
-        first, try renaming the capture buffer file to the new name. */
+         first, try renaming the capture buffer file to the new name. */
 #ifndef _WIN32
       if (ws_rename(cf->filename, fname) == 0) {
-       /* That succeeded - there's no need to copy the source file. */
-       from_filename = NULL;
-       do_copy = FALSE;
+        /* That succeeded - there's no need to copy the source file. */
+        from_filename = NULL;
+    do_copy = FALSE;
       } else {
-       if (errno == EXDEV) {
-         /* They're on different file systems, so we have to copy the
-            file. */
-         do_copy = TRUE;
+        if (errno == EXDEV) {
+          /* They're on different file systems, so we have to copy the
+             file. */
+          do_copy = TRUE;
           from_filename = cf->filename;
-       } else {
-         /* The rename failed, but not because they're on different
-            file systems - put up an error message.  (Or should we
-            just punt and try to copy?  The only reason why I'd
-            expect the rename to fail and the copy to succeed would
-            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?) */
-         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
-                               file_rename_error_message(errno), fname);
-         goto fail;
-       }
+        } else {
+          /* The rename failed, but not because they're on different
+             file systems - put up an error message.  (Or should we
+             just punt and try to copy?  The only reason why I'd
+             expect the rename to fail and the copy to succeed would
+             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?) */
+          simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
+                        file_rename_error_message(errno), fname);
+          goto fail;
+        }
       }
 #else
       do_copy = TRUE;
@@ -3744,14 +4421,14 @@ cf_save(capture_file *cf, const char *fname, packet_range_t *range, guint save_f
     if (do_copy) {
       /* Copy the file, if we haven't moved it. */
       if (!copy_file_binary_mode(from_filename, fname))
-       goto fail;
+    goto fail;
     }
   } else {
     /* Either we're filtering packets, or we're saving in a different
        format; we can't do that by copying or moving the capture file,
        we have to do it by writing the packets out in Wiretap. */
     pdh = wtap_dump_open(fname, save_format, cf->lnk_t, cf->snap,
-               compressed, &err);
+        compressed, &err);
     if (pdh == NULL) {
       cf_open_failure_alert_box(fname, err, NULL, TRUE, save_format);
       goto fail;
@@ -3796,7 +4473,7 @@ cf_save(capture_file *cf, const char *fname, packet_range_t *range, guint save_f
     }
   }
 
-  cf_callback_invoke(cf_cb_file_safe_finished, NULL);
+  cf_callback_invoke(cf_cb_file_save_finished, NULL);
 
   if (packet_range_process_all(range)) {
     /* We saved the entire capture, not just some packets from it.
@@ -3814,29 +4491,30 @@ cf_save(capture_file *cf, const char *fname, packet_range_t *range, guint save_f
     if ((cf_open(cf, fname, FALSE, &err)) == CF_OK) {
       /* XXX - report errors if this fails?
          What should we return if it fails or is aborted? */
-      switch (cf_read(cf)) {
+
+      switch (cf_read(cf, TRUE)) {
 
       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;
+    /* 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 CF_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; "cf_close()" set them
-          correctly for the "no capture file open" state). */
-       break;
+    /* The user bailed out of re-reading the capture file; the
+       capture file has been closed - just return (without
+       changing any menu settings; "cf_close()" set them
+       correctly for the "no capture file open" state). */
+    break;
       }
-      cf_callback_invoke(cf_cb_file_safe_reload_finished, NULL);
+      cf_callback_invoke(cf_cb_file_save_reload_finished, cf);
     }
   }
   return CF_OK;
 
 fail:
-  cf_callback_invoke(cf_cb_file_safe_failed, NULL);
+  cf_callback_invoke(cf_cb_file_save_failed, NULL);
   return CF_ERROR;
 }
 
@@ -3850,116 +4528,116 @@ cf_open_failure_alert_box(const char *filename, int err, gchar *err_info,
 
     case WTAP_ERR_NOT_REGULAR_FILE:
       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
-                   "The file \"%s\" is a \"special file\" or socket or other non-regular file.",
-                   filename);
+            "The file \"%s\" is a \"special file\" or socket or other non-regular file.",
+            filename);
       break;
 
     case WTAP_ERR_RANDOM_OPEN_PIPE:
       /* Seen only when opening a capture file for reading. */
       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
-                   "The file \"%s\" is a pipe or FIFO; Wireshark can't read pipe or FIFO files.",
-                   filename);
+            "The file \"%s\" is a pipe or FIFO; Wireshark can't read pipe or FIFO files.",
+            filename);
       break;
 
     case WTAP_ERR_FILE_UNKNOWN_FORMAT:
       /* Seen only when opening a capture file for reading. */
       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
-                   "The file \"%s\" isn't a capture file in a format Wireshark understands.",
-                   filename);
+            "The file \"%s\" isn't a capture file in a format Wireshark understands.",
+            filename);
       break;
 
     case WTAP_ERR_UNSUPPORTED:
       /* Seen only when opening a capture file for reading. */
       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
-                   "The file \"%s\" isn't a capture file in a format Wireshark understands.\n"
-                   "(%s)",
-                   filename, err_info);
+            "The file \"%s\" isn't a capture file in a format Wireshark understands.\n"
+            "(%s)",
+            filename, err_info);
       g_free(err_info);
       break;
 
     case WTAP_ERR_CANT_WRITE_TO_PIPE:
       /* Seen only when opening a capture file for writing. */
       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
-                   "The file \"%s\" is a pipe, and %s capture files can't be "
-                   "written to a pipe.",
-                   filename, wtap_file_type_string(file_type));
+            "The file \"%s\" is a pipe, and %s capture files can't be "
+            "written to a pipe.",
+            filename, wtap_file_type_string(file_type));
       break;
 
     case WTAP_ERR_UNSUPPORTED_FILE_TYPE:
       /* Seen only when opening a capture file for writing. */
       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
-                   "Wireshark doesn't support writing capture files in that format.");
+            "Wireshark doesn't support writing capture files in that format.");
       break;
 
     case WTAP_ERR_UNSUPPORTED_ENCAP:
       if (for_writing) {
-       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
-                     "Wireshark can't save this capture in that format.");
+    simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
+              "Wireshark can't save this capture in that format.");
       } else {
-       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
-                     "The file \"%s\" is a capture for a network type that Wireshark doesn't support.\n"
-                     "(%s)",
-                     filename, err_info);
+    simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
+              "The file \"%s\" is a capture for a network type that Wireshark doesn't support.\n"
+              "(%s)",
+              filename, err_info);
         g_free(err_info);
       }
       break;
 
     case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
       if (for_writing) {
-       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
-                     "Wireshark can't save this capture in that format.");
+    simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
+              "Wireshark can't save this capture in that format.");
       } else {
-       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
-                     "The file \"%s\" is a capture for a network type that Wireshark doesn't support.",
-                     filename);
+    simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
+              "The file \"%s\" is a capture for a network type that Wireshark doesn't support.",
+              filename);
       }
       break;
 
     case WTAP_ERR_BAD_RECORD:
       /* Seen only when opening a capture file for reading. */
       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
-                   "The file \"%s\" appears to be damaged or corrupt.\n"
-                   "(%s)",
-                   filename, err_info);
+            "The file \"%s\" appears to be damaged or corrupt.\n"
+            "(%s)",
+            filename, err_info);
       g_free(err_info);
       break;
 
     case WTAP_ERR_CANT_OPEN:
       if (for_writing) {
-       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
-                     "The file \"%s\" could not be created for some unknown reason.",
-                     filename);
+    simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
+              "The file \"%s\" could not be created for some unknown reason.",
+              filename);
       } else {
-       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
-                     "The file \"%s\" could not be opened for some unknown reason.",
-                     filename);
+    simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
+              "The file \"%s\" could not be opened for some unknown reason.",
+              filename);
       }
       break;
 
     case WTAP_ERR_SHORT_READ:
       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
-                   "The file \"%s\" appears to have been cut short"
-                   " in the middle of a packet or other data.",
-                   filename);
+            "The file \"%s\" appears to have been cut short"
+            " in the middle of a packet or other data.",
+            filename);
       break;
 
     case WTAP_ERR_SHORT_WRITE:
       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
-                   "A full header couldn't be written to the file \"%s\".",
-                   filename);
+            "A full header couldn't be written to the file \"%s\".",
+            filename);
       break;
 
     case WTAP_ERR_COMPRESSION_NOT_SUPPORTED:
       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
-                   "Gzip compression not supported by this file type.");
+            "Gzip compression not supported by this file type.");
       break;
 
     default:
       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
-                   "The file \"%s\" could not be %s: %s.",
-                   filename,
-                   for_writing ? "created" : "opened",
-                   wtap_strerror(err));
+            "The file \"%s\" could not be %s: %s.",
+            filename,
+            for_writing ? "created" : "opened",
+            wtap_strerror(err));
       break;
     }
   } else {
@@ -3986,52 +4664,22 @@ file_rename_error_message(int err)
 
   default:
     g_snprintf(errmsg_errno, sizeof(errmsg_errno),
-                   "The file \"%%s\" could not be moved: %s.",
-                               wtap_strerror(err));
+            "The file \"%%s\" could not be moved: %s.",
+                wtap_strerror(err));
     errmsg = errmsg_errno;
     break;
   }
   return errmsg;
 }
 
-char *
-cf_read_error_message(int err, gchar *err_info)
-{
-  static char errmsg_errno[1024+1];
-
-  switch (err) {
-
-  case WTAP_ERR_UNSUPPORTED_ENCAP:
-    g_snprintf(errmsg_errno, sizeof(errmsg_errno),
-               "The file \"%%s\" has a packet with a network type that Wireshark doesn't support.\n(%s)",
-               err_info);
-    g_free(err_info);
-    break;
-
-  case WTAP_ERR_BAD_RECORD:
-    g_snprintf(errmsg_errno, sizeof(errmsg_errno),
-            "An error occurred while reading from the file \"%%s\": %s.\n(%s)",
-            wtap_strerror(err), err_info);
-    g_free(err_info);
-    break;
-
-  default:
-    g_snprintf(errmsg_errno, sizeof(errmsg_errno),
-            "An error occurred while reading from the file \"%%s\": %s.",
-            wtap_strerror(err));
-    break;
-  }
-  return errmsg_errno;
-}
-
 static void
 cf_write_failure_alert_box(const char *filename, int err)
 {
   if (err < 0) {
     /* Wiretap error. */
     simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
-                 "An error occurred while writing to the file \"%s\": %s.",
-                 filename, wtap_strerror(err));
+          "An error occurred while writing to the file \"%s\": %s.",
+          filename, wtap_strerror(err));
   } else {
     /* OS error. */
     write_failure_alert_box(filename, err);
@@ -4051,20 +4699,20 @@ cf_close_failure_alert_box(const char *filename, int err)
 
     case WTAP_ERR_CANT_CLOSE:
       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
-                   "The file \"%s\" couldn't be closed for some unknown reason.",
-                   filename);
+            "The file \"%s\" couldn't be closed for some unknown reason.",
+            filename);
       break;
 
     case WTAP_ERR_SHORT_WRITE:
       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
-                   "Not all the packets could be written to the file \"%s\".",
+            "Not all the packets could be written to the file \"%s\".",
                     filename);
       break;
 
     default:
       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
-                   "An error occurred while closing the file \"%s\": %s.",
-                   filename, wtap_strerror(err));
+            "An error occurred while closing the file \"%s\": %s.",
+            filename, wtap_strerror(err));
       break;
     }
   } else {
@@ -4095,7 +4743,7 @@ cf_reload(capture_file *cf) {
   is_tempfile = cf->is_tempfile;
   cf->is_tempfile = FALSE;
   if (cf_open(cf, filename, is_tempfile, &err) == CF_OK) {
-    switch (cf_read(cf)) {
+    switch (cf_read(cf, FALSE)) {
 
     case CF_READ_OK:
     case CF_READ_ERROR:
@@ -4125,3 +4773,16 @@ cf_reload(capture_file *cf) {
      we should free up our copy. */
   g_free(filename);
 }
+
+/*
+ * Editor modelines
+ *
+ * Local Variables:
+ * c-basic-offset: 2
+ * tab-width: 8
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * ex: set shiftwidth=2 tabstop=8 expandtab
+ * :indentSize=2:tabSize=8:noTabs=true:
+ */