Store pointers to previously displayed and captured packet, not nstime_t deltas.
[metze/wireshark/wip.git] / file.c
diff --git a/file.c b/file.c
index 54dbc5f168c9811a717bfa4ae396228ec3b07744..ced94b7d0b492c59f7cc4a265abe37b8aa75d4b7 100644 (file)
--- a/file.c
+++ b/file.c
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
+#include "config.h"
 
 #ifdef HAVE_UNISTD_H
 #include <unistd.h>
@@ -83,8 +81,8 @@ gboolean auto_scroll_live;
 
 static guint32 cum_bytes;
 static nstime_t first_ts;
-static nstime_t prev_dis_ts;
-static nstime_t prev_cap_ts;
+static frame_data *prev_dis;
+static frame_data *prev_cap;
 
 static gulong computed_elapsed;
 
@@ -127,7 +125,7 @@ static gboolean find_packet(capture_file *cf,
 static void cf_open_failure_alert_box(const char *filename, int err,
                       gchar *err_info, gboolean for_writing,
                       int file_type);
-static const char *file_rename_error_message(int err);
+static void cf_rename_failure_alert_box(const char *filename, int err);
 static void cf_close_failure_alert_box(const char *filename, int err);
 static void ref_time_packets(capture_file *cf);
 /* Update the progress bar this many times when reading a file. */
@@ -143,7 +141,7 @@ static void ref_time_packets(capture_file *cf);
  */
 typedef struct {
   cf_callback_t cb_fct;
-  gpointer user_data;
+  gpointer      user_data;
 } cf_callback_data_t;
 
 static GList *cf_callbacks = NULL;
@@ -152,12 +150,12 @@ static void
 cf_callback_invoke(int event, gpointer data)
 {
   cf_callback_data_t *cb;
-  GList *cb_item = cf_callbacks;
+  GList              *cb_item = cf_callbacks;
 
   /* there should be at least one interested */
   g_assert(cb_item != NULL);
 
-  while(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);
@@ -181,11 +179,11 @@ void
 cf_callback_remove(cf_callback_t func)
 {
   cf_callback_data_t *cb;
-  GList *cb_item = cf_callbacks;
+  GList              *cb_item = cf_callbacks;
 
-  while(cb_item != NULL) {
+  while (cb_item != NULL) {
     cb = cb_item->data;
-    if(cb->cb_fct == func) {
+    if (cb->cb_fct == func) {
       cf_callbacks = g_list_remove(cf_callbacks, cb);
       g_free(cb);
       return;
@@ -204,12 +202,12 @@ cf_timestamp_auto_precision(capture_file *cf)
 
 
   /* don't try to get the file's precision if none is opened */
-  if(cf->state == FILE_CLOSED) {
+  if (cf->state == FILE_CLOSED) {
     return;
   }
 
   /* if we are in auto mode, set precision of current file */
-  if(prec == TS_PREC_AUTO ||
+  if (prec == TS_PREC_AUTO ||
      prec == TS_PREC_AUTO_SEC ||
      prec == TS_PREC_AUTO_DSEC ||
      prec == TS_PREC_AUTO_CSEC ||
@@ -244,7 +242,7 @@ cf_timestamp_auto_precision(capture_file *cf)
      "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);
+      packet_list_resize_column(i);
     }
   }
 }
@@ -262,8 +260,8 @@ static void reset_elapsed(void)
 
 static void compute_elapsed(GTimeVal *start_time)
 {
-  gdouble    delta_time;
-  GTimeVal   time_now;
+  gdouble  delta_time;
+  GTimeVal time_now;
 
   g_get_current_time(&time_now);
 
@@ -276,8 +274,8 @@ static void compute_elapsed(GTimeVal *start_time)
 cf_status_t
 cf_open(capture_file *cf, const char *fname, gboolean is_tempfile, int *err)
 {
-  wtap       *wth;
-  gchar       *err_info;
+  wtap  *wth;
+  gchar *err_info;
 
   wth = wtap_open_offline(fname, err, &err_info, TRUE);
   if (wth == NULL)
@@ -312,7 +310,9 @@ cf_open(capture_file *cf, const char *fname, gboolean is_tempfile, int *err)
   reset_elapsed();
 
   cf->cd_t        = wtap_file_type(cf->wth);
+  cf->linktypes = g_array_sized_new(FALSE, FALSE, (guint) sizeof(int), 1);
   cf->count     = 0;
+  cf->packet_comment_count = 0;
   cf->displayed_count = 0;
   cf->marked_count = 0;
   cf->ignored_count = 0;
@@ -332,17 +332,17 @@ cf_open(capture_file *cf, const char *fname, gboolean is_tempfile, int *err)
 
   nstime_set_zero(&cf->elapsed_time);
   nstime_set_unset(&first_ts);
-  nstime_set_unset(&prev_dis_ts);
-  nstime_set_unset(&prev_cap_ts);
+  prev_dis = NULL;
+  prev_cap = NULL;
   cum_bytes = 0;
 
   /* Adjust timestamp precision if auto is selected, col width will be adjusted */
   cf_timestamp_auto_precision(cf);
   /* XXX needed ? */
-  new_packet_list_queue_draw();
+  packet_list_queue_draw();
   fileset_file_opened(fname);
 
-  if(cf->cd_t == WTAP_FILE_BER) {
+  if (cf->cd_t == WTAP_FILE_BER) {
     /* tell the BER dissector the file name */
     ber_set_filename(cf->filename);
   }
@@ -357,6 +357,21 @@ fail:
   return CF_ERROR;
 }
 
+/*
+ * Add an encapsulation type to cf->linktypes.
+ */
+void
+cf_add_encapsulation_type(capture_file *cf, int encap)
+{
+  guint i;
+
+  for (i = 0; i < cf->linktypes->len; i++) {
+    if (g_array_index(cf->linktypes, gint, i) == encap)
+      return; /* it's already there */
+  }
+  /* It's not already there - add it. */
+  g_array_append_val(cf->linktypes, encap);
+}
 
 /*
  * Reset the state for the currently closed file, but don't do the
@@ -411,10 +426,14 @@ cf_reset_state(capture_file *cf)
   cf->current_row = 0;
   cf->finfo_selected = NULL;
 
+  /* No frame link-layer types, either. */
+  g_array_free(cf->linktypes, TRUE);
+  cf->linktypes = NULL;
+
   /* Clear the packet list. */
-  new_packet_list_freeze();
-  new_packet_list_clear();
-  new_packet_list_thaw();
+  packet_list_freeze();
+  packet_list_clear();
+  packet_list_thaw();
 
   cf->f_datalen = 0;
   nstime_set_zero(&cf->elapsed_time);
@@ -431,7 +450,7 @@ cf_reset_state(capture_file *cf)
 void
 cf_close(capture_file *cf)
 {
-  if(cf->state != FILE_CLOSED) {
+  if (cf->state != FILE_CLOSED) {
     cf_callback_invoke(cf_cb_file_closing, cf);
 
   /* close things, if not already closed before */
@@ -443,16 +462,10 @@ cf_close(capture_file *cf)
   }
 }
 
-/* an out of memory exception occured, wait for a user button press to exit */
-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;
+  float progbar_val;
 
   progbar_val = (gfloat) file_pos / (gfloat) size;
   if (progbar_val > 1.0) {
@@ -482,31 +495,29 @@ calc_progbar_val(capture_file *cf, gint64 size, gint64 file_pos, gchar *status_s
 }
 
 cf_read_status_t
-cf_read(capture_file *cf, gboolean from_save)
+cf_read(capture_file *cf, gboolean reloading)
 {
-  int         err;
-  gchar       *err_info;
-  const gchar *name_ptr;
-  const char  *errmsg;
-  char         errmsg_errno[1024+1];
-  gint64       data_offset;
-  gint64       file_pos;
-  progdlg_t *volatile progbar = NULL;
-  gboolean     stop_flag;
-  volatile gint64 size;
-  volatile float progbar_val;
-  GTimeVal     start_time;
-  gchar        status_str[100];
-  volatile gint64 progbar_nextstep;
-  volatile gint64 progbar_quantum;
-  dfilter_t   *dfcode;
-  gboolean    filtering_tap_listeners;
-  guint       tap_flags;
-  volatile int count = 0;
+  int                  err;
+  gchar               *err_info;
+  gchar               *name_ptr;
+  gint64               data_offset;
+  gint64               file_pos;
+  progdlg_t *volatile  progbar        = NULL;
+  gboolean             stop_flag;
+  volatile gint64      size;
+  volatile float       progbar_val;
+  GTimeVal             start_time;
+  gchar                status_str[100];
+  volatile gint64      progbar_nextstep;
+  volatile gint64      progbar_quantum;
+  dfilter_t           *dfcode;
+  gboolean             filtering_tap_listeners;
+  guint                tap_flags;
+  volatile int         count          = 0;
 #ifdef HAVE_LIBPCAP
-  volatile int displayed_once = 0;
+  volatile int         displayed_once = 0;
 #endif
-  gboolean compiled;
+  gboolean             compiled;
 
   /* Compile the current display filter.
    * We assume this will not fail since cf->dfilter is only set in
@@ -523,12 +534,16 @@ cf_read(capture_file *cf, gboolean from_save)
 
   reset_tap_listeners();
 
-  name_ptr = get_basename(cf->filename);
+  name_ptr = g_filename_display_basename(cf->filename);
 
-  if (from_save == FALSE)
-    cf_callback_invoke(cf_cb_file_read_started, cf);
+  if (reloading)
+    cf_callback_invoke(cf_cb_file_reload_started, cf);
   else
-    cf_callback_invoke(cf_cb_file_save_started, (gpointer)name_ptr);
+    cf_callback_invoke(cf_cb_file_read_started, cf);
+
+  /* Record whether the file is compressed.
+     XXX - do we know this at open time? */
+  cf->iscompressed = wtap_iscompressed(cf->wth);
 
   /* Find the size of the file. */
   size = wtap_file_size(cf->wth, NULL);
@@ -537,7 +552,7 @@ cf_read(capture_file *cf, gboolean from_save)
   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;
     if (progbar_quantum < MIN_QUANTUM)
       progbar_quantum = MIN_QUANTUM;
@@ -546,8 +561,8 @@ cf_read(capture_file *cf, gboolean from_save)
   /* Progress so far. */
   progbar_val = 0.0f;
 
-  /* The packet list window will be empty untill the file is completly loaded */
-  new_packet_list_freeze();
+  /* The packet list window will be empty until the file is completly loaded */
+  packet_list_freeze();
 
   stop_flag = FALSE;
   g_get_current_time(&start_time);
@@ -560,13 +575,13 @@ cf_read(capture_file *cf, gboolean from_save)
       /* Create the progress bar if necessary.
        * Check whether it should be created or not every MIN_NUMBER_OF_PACKET
        */
-      if ((progbar == NULL) && !(count % MIN_NUMBER_OF_PACKET)){
+      if ((progbar == NULL) && !(count % MIN_NUMBER_OF_PACKET)) {
         progbar_val = calc_progbar_val(cf, size, file_pos, status_str, sizeof(status_str));
-        if (from_save == FALSE)
-          progbar = delayed_create_progress_dlg("Loading", name_ptr,
+        if (reloading)
+          progbar = delayed_create_progress_dlg(cf->window, "Reloading", name_ptr,
                                                 TRUE, &stop_flag, &start_time, progbar_val);
         else
-          progbar = delayed_create_progress_dlg("Saving", name_ptr,
+          progbar = delayed_create_progress_dlg(cf->window, "Loading", name_ptr,
                                                 TRUE, &stop_flag, &start_time, progbar_val);
       }
 
@@ -606,30 +621,26 @@ cf_read(capture_file *cf, gboolean from_save)
       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); */
-      };
+      simple_message_box(ESD_TYPE_ERROR, NULL,
+                     "Some infos / workarounds can be found at:\n"
+                     "http://wiki.wireshark.org/KnownBugs/OutOfMemory",
+                     "Sorry, but Wireshark has run out of memory and has to terminate now!");
+#if 0
+      /* Could we close the current capture and free up memory from that? */
       break;
+#else
+      /* we have to terminate, as we cannot recover from the memory error */
+      exit(1);
+#endif
     }
     ENDTRY;
   }
 
+  /* Free the display name */
+  g_free(name_ptr);
+
   /* Cleanup and release all dfilter resources */
-  if (dfcode != NULL){
+  if (dfcode != NULL) {
     dfilter_free(dfcode);
   }
 
@@ -659,27 +670,25 @@ cf_read(capture_file *cf, gboolean from_save)
   cf->current_frame = frame_data_sequence_find(cf->frames, cf->first_displayed);
   cf->current_row = 0;
 
-  new_packet_list_thaw();
-  if (from_save == FALSE)
-    cf_callback_invoke(cf_cb_file_read_finished, cf);
+  packet_list_thaw();
+  if (reloading)
+    cf_callback_invoke(cf_cb_file_reload_finished, cf);
   else
-    cf_callback_invoke(cf_cb_file_save_finished, cf);
+    cf_callback_invoke(cf_cb_file_read_finished, cf);
 
   /* If we have any displayed packets to select, select the first of those
      packets by making the first row the selected row. */
-  if (cf->first_displayed != 0){
-    new_packet_list_select_first_row();
+  if (cf->first_displayed != 0) {
+    packet_list_select_first_row();
   }
 
-  if(stop_flag) {
-    simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
-                  "%sFile loading was cancelled!%s\n"
-                  "\n"
+  if (stop_flag) {
+    simple_message_box(ESD_TYPE_WARN, NULL,
                   "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());
+                  "File loading was cancelled!");
     return CF_READ_ERROR;
   }
 
@@ -690,55 +699,51 @@ cf_read(capture_file *cf, gboolean from_save)
     switch (err) {
 
     case WTAP_ERR_UNSUPPORTED:
-      g_snprintf(errmsg_errno, sizeof(errmsg_errno),
-                 "The capture file contains record data that TShark doesn't support.\n(%s)",
+      simple_error_message_box(
+                 "The capture file contains record data that Wireshark doesn't support.\n(%s)",
                  err_info);
       g_free(err_info);
-      errmsg = errmsg_errno;
       break;
 
     case WTAP_ERR_UNSUPPORTED_ENCAP:
-      g_snprintf(errmsg_errno, sizeof(errmsg_errno),
+      simple_error_message_box(
                  "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.";
+      simple_error_message_box(
+                 "An attempt to read from the capture file failed for"
+                 " 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.";
+      simple_error_message_box(
+                 "The capture file appears to have been cut short"
+                 " in the middle of a packet.");
       break;
 
     case WTAP_ERR_BAD_FILE:
-      g_snprintf(errmsg_errno, sizeof(errmsg_errno),
+      simple_error_message_box(
                  "The capture file appears to be damaged or corrupt.\n(%s)",
                  err_info);
       g_free(err_info);
-      errmsg = errmsg_errno;
       break;
 
     case WTAP_ERR_DECOMPRESS:
-      g_snprintf(errmsg_errno, sizeof(errmsg_errno),
+      simple_error_message_box(
                  "The compressed 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),
+      simple_error_message_box(
                  "An error occurred while reading the"
                  " capture file: %s.", wtap_strerror(err));
-      errmsg = errmsg_errno;
       break;
     }
-    simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", errmsg);
     return CF_READ_ERROR;
   } else
     return CF_READ_OK;
@@ -757,13 +762,13 @@ cf_start_tail(capture_file *cf, const char *fname, gboolean is_tempfile, int *er
 cf_read_status_t
 cf_continue_tail(capture_file *cf, volatile int to_read, int *err)
 {
-  gint64 data_offset = 0;
-  gchar *err_info;
-  volatile int newly_displayed_packets = 0;
-  dfilter_t   *dfcode;
-  gboolean filtering_tap_listeners;
-  guint tap_flags;
-  gboolean compiled;
+  gint64        data_offset             = 0;
+  gchar        *err_info;
+  volatile int  newly_displayed_packets = 0;
+  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
@@ -780,9 +785,9 @@ cf_continue_tail(capture_file *cf, volatile int to_read, int *err)
 
   *err = 0;
 
-  new_packet_list_check_end();
+  packet_list_check_end();
   /* Don't freeze/thaw the list when doing live capture */
-  /*new_packet_list_freeze();*/
+  /*packet_list_freeze();*/
 
   /*g_log(NULL, G_LOG_LEVEL_MESSAGE, "cf_continue_tail: %u new: %u", cf->count, to_read);*/
 
@@ -804,36 +809,28 @@ cf_continue_tail(capture_file *cf, volatile int to_read, int *err)
       }
     }
     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); */
-      };
-      /* Don't freeze/thaw the list when doing live capture */
-      /*new_packet_list_thaw();*/
+      simple_message_box(ESD_TYPE_ERROR, NULL,
+                     "Some infos / workarounds can be found at:\n"
+                     "http://wiki.wireshark.org/KnownBugs/OutOfMemory",
+                     "Sorry, but Wireshark has run out of memory and has to terminate now!");
+#if 0
+      /* Could we close the current capture and free up memory from that? */
       return CF_READ_ABORTED;
+#else
+      /* we have to terminate, as we cannot recover from the memory error */
+      exit(1);
+#endif
     }
     ENDTRY;
     to_read--;
   }
 
+  /* Update the file encapsulation; it might have changed based on the
+     packets we've read. */
+  cf->lnk_t = wtap_file_encap(cf->wth);
+
   /* Cleanup and release all dfilter resources */
-  if (dfcode != NULL){
+  if (dfcode != NULL) {
     dfilter_free(dfcode);
   }
 
@@ -841,17 +838,17 @@ cf_continue_tail(capture_file *cf, volatile int to_read, int *err)
     cf->count, cf->state, *err);*/
 
   /* Don't freeze/thaw the list when doing live capture */
-  /*new_packet_list_thaw();*/
+  /*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();
+  if (!cf->current_frame)
+    packet_list_select_first_row();
 
   /* moving to the end of the packet list - if the user requested so and
      we have some new packets. */
   if (newly_displayed_packets && auto_scroll_live && cf->count != 0)
-      new_packet_list_moveto_end();
+      packet_list_moveto_end();
 
   if (cf->state == FILE_READ_ABORTED) {
     /* Well, the user decided to exit Wireshark.  Return CF_READ_ABORTED
@@ -863,8 +860,9 @@ 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\" (\"%s\")",
+        wtap_strerror(*err), err_info, cf->filename);
+    g_free(err_info);
 
     return CF_READ_ERROR;
   } else
@@ -879,12 +877,12 @@ cf_fake_continue_tail(capture_file *cf) {
 cf_read_status_t
 cf_finish_tail(capture_file *cf, int *err)
 {
-  gchar *err_info;
-  gint64 data_offset;
-  dfilter_t   *dfcode;
-  gboolean filtering_tap_listeners;
-  guint tap_flags;
-  gboolean compiled;
+  gchar     *err_info;
+  gint64     data_offset;
+  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
@@ -899,32 +897,32 @@ cf_finish_tail(capture_file *cf, int *err)
   /* Get the union of the flags for all tap listeners. */
   tap_flags = union_of_tap_listener_flags();
 
-  if(cf->wth == NULL) {
+  if (cf->wth == NULL) {
     cf_close(cf);
     return CF_READ_ERROR;
   }
 
-  new_packet_list_check_end();
+  packet_list_check_end();
   /* Don't freeze/thaw the list when doing live capture */
-  /*new_packet_list_freeze();*/
+  /*packet_list_freeze();*/
 
   while ((wtap_read(cf->wth, err, &err_info, &data_offset))) {
     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);
   }
 
   /* Cleanup and release all dfilter resources */
-  if (dfcode != NULL){
+  if (dfcode != NULL) {
     dfilter_free(dfcode);
   }
 
   /* Don't freeze/thaw the list when doing live capture */
-  /*new_packet_list_thaw();*/
+  /*packet_list_thaw();*/
 
   if (cf->state == FILE_READ_ABORTED) {
     /* Well, the user decided to abort the read.  We're only called
@@ -937,7 +935,7 @@ cf_finish_tail(capture_file *cf, int *err)
   }
 
   if (auto_scroll_live && cf->count != 0)
-    new_packet_list_moveto_end();
+    packet_list_moveto_end();
 
   /* We're done reading sequentially through the file. */
   cf->state = FILE_READ_DONE;
@@ -950,15 +948,21 @@ cf_finish_tail(capture_file *cf, int *err)
    * don't need after the sequential run-through of the packets. */
   postseq_cleanup_all_protocols();
 
-  /* Set the file encapsulation type now; we don't know what it is until
-     we've looked at all the packets, as we don't know until then whether
-     there's more than one type (and thus whether it's
-     WTAP_ENCAP_PER_PACKET). */
+  /* Update the file encapsulation; it might have changed based on the
+     packets we've read. */
   cf->lnk_t = wtap_file_encap(cf->wth);
 
+  /* Update the details in the file-set dialog, as the capture file
+   * has likely grown since we first stat-ed it */
+  fileset_update_file(cf->filename);
+
   if (*err != 0) {
     /* We got an error reading the capture file.
        XXX - pop up a dialog box? */
+
+    g_warning("Error \"%s\" while reading: \"%s\" (\"%s\")",
+        wtap_strerror(*err), err_info, cf->filename);
+    g_free(err_info);
     return CF_READ_ERROR;
   } else {
     return CF_READ_OK;
@@ -966,26 +970,27 @@ cf_finish_tail(capture_file *cf, int *err)
 }
 #endif /* HAVE_LIBPCAP */
 
-const gchar *
+gchar *
 cf_get_display_name(capture_file *cf)
 {
-  const gchar *displayname;
+  gchar *displayname;
 
   /* Return a name to use in displays */
   if (!cf->is_tempfile) {
     /* Get the last component of the file name, and use that. */
-    if (cf->filename){
-      displayname = get_basename(cf->filename);
+    if (cf->filename) {
+      displayname = g_filename_display_basename(cf->filename);
     } else {
-      displayname="(No file)";
+      displayname=g_strdup("(No file)");
     }
   } else {
-    /* The file we read is a temporary file from a live capture;
-       we don't mention its name. */
+    /* The file we read is a temporary file from a live capture or
+       a merge operation; we don't mention its name, but, if it's
+       from a capture, give the source of the capture. */
     if (cf->source) {
-      displayname = cf->source;
+      displayname = g_strdup(cf->source);
     } else {
-      displayname = "(Untitled)";
+      displayname = g_strdup("(Untitled)");
     }
   }
   return displayname;
@@ -1070,9 +1075,9 @@ void cf_set_rfcode(capture_file *cf, dfilter_t *rfcode)
 static void
 find_and_mark_frame_depended_upon(gpointer data, gpointer user_data)
 {
-  frame_data *dependent_fd;
-  guint32 dependent_frame = GPOINTER_TO_UINT(data);
-  capture_file *cf = (capture_file *)user_data;
+  frame_data   *dependent_fd;
+  guint32       dependent_frame = GPOINTER_TO_UINT(data);
+  capture_file *cf              = (capture_file *)user_data;
 
   dependent_fd = frame_data_sequence_find(cf->frames, dependent_frame);
   dependent_fd->flags.dependent_of_displayed = 1;
@@ -1086,15 +1091,16 @@ add_packet_to_packet_list(frame_data *fdata, capture_file *cf,
     gboolean refilter,
     gboolean add_to_packet_list)
 {
-  gboolean  create_proto_tree = FALSE;
-  epan_dissect_t edt;
-  column_info *cinfo;
-  gint row = -1;
+  gboolean        create_proto_tree = FALSE;
+  epan_dissect_t  edt;
+  column_info    *cinfo;
+  gint            row               = -1;
 
   cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
 
   frame_data_set_before_dissect(fdata, &cf->elapsed_time,
-                                &first_ts, &prev_dis_ts, &prev_cap_ts);
+                                &first_ts, prev_dis, prev_cap);
+  prev_cap = fdata;
 
   /* If either
     + we have a display filter and are re-applying it;
@@ -1138,17 +1144,18 @@ add_packet_to_packet_list(frame_data *fdata, capture_file *cf,
   } else
     fdata->flags.passed_dfilter = 1;
 
-  if(fdata->flags.passed_dfilter || fdata->flags.ref_time)
+  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);
+      row = packet_list_append(cinfo, fdata, &edt.pi);
   }
 
-  if(fdata->flags.passed_dfilter || fdata->flags.ref_time)
+  if (fdata->flags.passed_dfilter || fdata->flags.ref_time)
   {
-    frame_data_set_after_dissect(fdata, &cum_bytes, &prev_dis_ts);
+    frame_data_set_after_dissect(fdata, &cum_bytes);
+    prev_dis = fdata;
 
     /* If we haven't yet seen the first frame, this is it.
 
@@ -1180,7 +1187,7 @@ static int
 read_packet(capture_file *cf, dfilter_t *dfcode,
             gboolean filtering_tap_listeners, guint tap_flags, gint64 offset)
 {
-  const struct wtap_pkthdr *phdr = wtap_phdr(cf->wth);
+  const struct wtap_pkthdr *phdr          = wtap_phdr(cf->wth);
   union wtap_pseudo_header *pseudo_header = wtap_pseudoheader(cf->wth);
   const guchar *buf = wtap_buf_ptr(cf->wth);
   frame_data    fdlocal;
@@ -1189,8 +1196,16 @@ read_packet(capture_file *cf, dfilter_t *dfcode,
   int           passed;
   int           row = -1;
 
+  /* Add this packet's link-layer encapsulation type to cf->linktypes, if
+     it's not already there.
+     XXX - yes, this is O(N), so if every packet had a different
+     link-layer encapsulation type, it'd be O(N^2) to read the file, but
+     there are probably going to be a small number of encapsulation types
+     in a file. */
+  cf_add_encapsulation_type(cf, phdr->pkt_encap);
+
   /* The frame number of this packet is one more than the count of
-     frames in this packet. */
+     frames in the file so far. */
   framenum = cf->count + 1;
 
   frame_data_init(&fdlocal, framenum, phdr, offset, cum_bytes);
@@ -1210,6 +1225,8 @@ read_packet(capture_file *cf, dfilter_t *dfcode,
     fdata = frame_data_sequence_add(cf->frames, &fdlocal);
 
     cf->count++;
+    if (fdlocal.opt_comment != NULL)
+      cf->packet_comment_count++;
     cf->f_datalen = offset + fdlocal.cap_len;
 
     if (!cf->redissecting) {
@@ -1226,27 +1243,28 @@ cf_status_t
 cf_merge_files(char **out_filenamep, int in_file_count,
                char *const *in_filenames, int file_type, gboolean do_append)
 {
-  merge_in_file_t  *in_files, *in_file;
-  char             *out_filename;
-  char             *tmpname;
-  int               out_fd;
-  wtap_dumper      *pdh;
-  int               open_err, read_err, write_err, close_err;
-  gchar            *err_info;
-  int               err_fileno;
-  int               i;
-  char              errmsg_errno[1024+1];
-  const char       *errmsg;
-  gboolean          got_read_error = FALSE, got_write_error = FALSE;
-  gint64            data_offset;
-  progdlg_t        *progbar = NULL;
-  gboolean          stop_flag;
-  gint64            f_len, file_pos;
-  float             progbar_val;
-  GTimeVal          start_time;
-  gchar             status_str[100];
-  gint64            progbar_nextstep;
-  gint64            progbar_quantum;
+  merge_in_file_t *in_files, *in_file;
+  char            *out_filename;
+  char            *tmpname;
+  int              out_fd;
+  wtap_dumper     *pdh;
+  int              open_err, read_err, write_err, close_err;
+  gchar           *err_info;
+  int              err_fileno;
+  int              i;
+  gboolean         got_read_error     = FALSE, got_write_error = FALSE;
+  gint64           data_offset;
+  progdlg_t       *progbar            = NULL;
+  gboolean         stop_flag;
+  gint64           f_len, file_pos;
+  float            progbar_val;
+  GTimeVal         start_time;
+  gchar            status_str[100];
+  gint64           progbar_nextstep;
+  gint64           progbar_quantum;
+  gchar           *display_basename;
+  int              selected_frame_type;
+  gboolean         fake_interface_ids = FALSE;
 
   /* open the input files */
   if (!merge_open_in_files(in_file_count, in_filenames, &in_files,
@@ -1277,17 +1295,108 @@ cf_merge_files(char **out_filenamep, int in_file_count,
     return CF_ERROR;
   }
 
-  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);
-  if (pdh == NULL) {
-    ws_close(out_fd);
-    merge_close_in_files(in_file_count, in_files);
-    g_free(in_files);
-    cf_open_failure_alert_box(out_filename, open_err, err_info, TRUE,
-                              file_type);
-    return CF_ERROR;
+  selected_frame_type = merge_select_frame_type(in_file_count, in_files);
+
+  /* If we are trying to merge a number of libpcap files with different encapsulation types
+   * change the output file type to pcapng and create SHB and IDB:s for the new file use the
+   * interface index stored in in_files per file to change the phdr before writing the datablock.
+   * XXX should it be an option to convert to pcapng?
+   *
+   * We need something similar when merging pcapng files possibly with an option to say
+   * the same interface(s) used in all in files. SHBs comments should be merged together.
+   */
+  if ((selected_frame_type == WTAP_ENCAP_PER_PACKET)&&(file_type == WTAP_FILE_PCAP)) {
+    /* Write output in pcapng format */
+    wtapng_section_t            *shb_hdr;
+    wtapng_iface_descriptions_t *idb_inf, *idb_inf_merge_file;
+    wtapng_if_descr_t            int_data, *file_int_data;
+    GString                     *comment_gstr;
+    int                          i;
+
+    fake_interface_ids = TRUE;
+    /* Create SHB info */
+    shb_hdr = wtap_file_get_shb_info(in_files[0].wth);
+    comment_gstr = g_string_new("");
+    g_string_append_printf(comment_gstr, "%s \n",shb_hdr->opt_comment);
+    g_string_append_printf(comment_gstr, "File created by merging: \n");
+    file_type = WTAP_FILE_PCAPNG;
+
+    for (i = 0; i < in_file_count; i++) {
+        g_string_append_printf(comment_gstr, "File%d: %s \n",i+1,in_files[i].filename);
+    }
+    shb_hdr->section_length = -1;
+    /* options */
+    shb_hdr->opt_comment   = g_string_free(comment_gstr, FALSE);  /* NULL if not available */
+    shb_hdr->shb_hardware  = NULL;        /* NULL if not available, UTF-8 string containing the        */
+                                          /*  description of the hardware used to create this section. */
+    shb_hdr->shb_os        = NULL;        /* NULL if not available, UTF-8 string containing the name   */
+                                          /*  of the operating system used to create this section.     */
+    shb_hdr->shb_user_appl = "Wireshark"; /* NULL if not available, UTF-8 string containing the name   */
+                                          /*  of the application used to create this section.          */
+
+    /* create fake IDB info */
+    idb_inf = g_new(wtapng_iface_descriptions_t,1);
+    idb_inf->number_of_interfaces = in_file_count; /* TODO make this the number of DIFFERENT encapsulation types
+                                                    * check that snaplength is the same too?
+                                                    */
+    idb_inf->interface_data = g_array_new(FALSE, FALSE, sizeof(wtapng_if_descr_t));
+
+    for (i = 0; i < in_file_count; i++) {
+      idb_inf_merge_file               = wtap_file_get_idb_info(in_files[i].wth);
+      /* read the interface data from the in file to our combined interfca data */
+      file_int_data = &g_array_index (idb_inf_merge_file->interface_data, wtapng_if_descr_t, 0);
+      int_data.wtap_encap            = file_int_data->wtap_encap;
+      int_data.time_units_per_second = file_int_data->time_units_per_second;
+      int_data.link_type             = file_int_data->link_type;
+      int_data.snap_len              = file_int_data->snap_len;
+      int_data.if_name               = g_strdup(file_int_data->if_name);
+      int_data.opt_comment           = NULL;
+      int_data.if_description        = NULL;
+      int_data.if_speed              = 0;
+      int_data.if_tsresol            = 6;
+      int_data.if_filter_str         = NULL;
+      int_data.bpf_filter_len        = 0;
+      int_data.if_filter_bpf_bytes   = NULL;
+      int_data.if_os                 = NULL;
+      int_data.if_fcslen             = -1;
+      int_data.num_stat_entries      = 0;          /* Number of ISB:s */
+      int_data.interface_statistics  = NULL;
+
+      g_array_append_val(idb_inf->interface_data, int_data);
+      g_free(idb_inf_merge_file);
+
+      /* Set fake interface Id in per file data */
+      in_files[i].interface_id = i;
+    }
+
+    pdh = wtap_dump_fdopen_ng(out_fd, file_type,
+                              selected_frame_type,
+                              merge_max_snapshot_length(in_file_count, in_files),
+                              FALSE /* compressed */, shb_hdr, idb_inf /* wtapng_iface_descriptions_t *idb_inf */, &open_err);
+
+    if (pdh == NULL) {
+      ws_close(out_fd);
+      merge_close_in_files(in_file_count, in_files);
+      g_free(in_files);
+      cf_open_failure_alert_box(out_filename, open_err, err_info, TRUE,
+                                file_type);
+      return CF_ERROR;
+    }
+
+  } else {
+
+    pdh = wtap_dump_fdopen(out_fd, file_type,
+                           selected_frame_type,
+                           merge_max_snapshot_length(in_file_count, in_files),
+                           FALSE /* compressed */, &open_err);
+    if (pdh == NULL) {
+      ws_close(out_fd);
+      merge_close_in_files(in_file_count, in_files);
+      g_free(in_files);
+      cf_open_failure_alert_box(out_filename, open_err, err_info, TRUE,
+                                file_type);
+      return CF_ERROR;
+    }
   }
 
   /* Get the sum of the sizes of all the files. */
@@ -1336,7 +1445,7 @@ cf_merge_files(char **out_filenamep, int in_file_count,
        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("Merging", "files",
+      progbar = delayed_create_progress_dlg(NULL, "Merging", "files",
         FALSE, &stop_flag, &start_time, progbar_val);
     }
 
@@ -1371,8 +1480,19 @@ cf_merge_files(char **out_filenamep, int in_file_count,
       break;
     }
 
+    /* If we have WTAP_ENCAP_PER_PACKETend the infiles are of type WTAP_FILE_PCAP
+     * we need to set the interface id in the paket header = the interface index we used
+     * in the IDBs interface description for this file(encapsulation type).
+     */
+    if (fake_interface_ids) {
+      struct wtap_pkthdr *phdr;
+
+      phdr = wtap_phdr(in_file->wth);
+      phdr->interface_id = in_file->interface_id;
+      phdr->presence_flags = phdr->presence_flags | WTAP_HAS_INTERFACE_ID;
+    }
     if (!wtap_dump(pdh, wtap_phdr(in_file->wth), wtap_pseudoheader(in_file->wth),
-         wtap_buf_ptr(in_file->wth), &write_err)) {
+                   wtap_buf_ptr(in_file->wth), &write_err)) {
       got_write_error = TRUE;
       break;
     }
@@ -1397,50 +1517,50 @@ cf_merge_files(char **out_filenamep, int in_file_count,
       if (in_files[i].state == GOT_ERROR) {
         /* Put up a message box noting that a read failed somewhere along
            the line. */
+        display_basename = g_filename_display_basename(in_files[i].filename);
         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);
+          simple_error_message_box(
+                     "The capture file %s has a packet with a network type that Wireshark doesn't support.\n(%s)",
+                     display_basename, 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.";
+          simple_error_message_box(
+                     "An attempt to read from the capture file %s failed for"
+                     " some unknown reason.", display_basename);
           break;
 
         case WTAP_ERR_SHORT_READ:
-          errmsg = "The capture file %s appears to have been cut short"
-                   " in the middle of a packet.";
+          simple_error_message_box(
+                     "The capture file %s appears to have been cut short"
+                      " in the middle of a packet.", display_basename);
           break;
 
         case WTAP_ERR_BAD_FILE:
-          g_snprintf(errmsg_errno, sizeof(errmsg_errno),
-                     "The capture file %%s appears to be damaged or corrupt.\n(%s)",
-                     err_info);
+          simple_error_message_box(
+                     "The capture file %s appears to be damaged or corrupt.\n(%s)",
+                     display_basename, err_info);
           g_free(err_info);
-          errmsg = errmsg_errno;
           break;
 
         case WTAP_ERR_DECOMPRESS:
-          g_snprintf(errmsg_errno, sizeof(errmsg_errno),
-                     "The compressed capture file %%s appears to be damaged or corrupt.\n"
-                     "(%s)", err_info);
+          simple_error_message_box(
+                     "The compressed capture file %s appears to be damaged or corrupt.\n"
+                     "(%s)", display_basename, err_info);
           g_free(err_info);
-          errmsg = errmsg_errno;
           break;
 
         default:
-          g_snprintf(errmsg_errno, sizeof(errmsg_errno),
+          simple_error_message_box(
                      "An error occurred while reading the"
-                     " capture file %%s: %s.", wtap_strerror(read_err));
-          errmsg = errmsg_errno;
+                     " capture file %s: %s.",
+                     display_basename,  wtap_strerror(read_err));
           break;
         }
-        simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, errmsg, in_files[i].filename);
+        g_free(display_basename);
       }
     }
   }
@@ -1456,16 +1576,20 @@ cf_merge_files(char **out_filenamep, int in_file_count,
          * This is a problem with the particular frame we're writing;
          * note that, and give the frame number.
          */
-        simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
+        display_basename = g_filename_display_basename(in_file->filename);
+        simple_error_message_box(
                       "Frame %u of \"%s\" has a network type that can't be saved in a \"%s\" file.",
-                      in_file->packet_num, in_file->filename,
+                      in_file->packet_num, display_basename,
                       wtap_file_type_string(file_type));
+        g_free(display_basename);
         break;
 
       default:
-        simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
+        display_basename = g_filename_display_basename(out_filename);
+        simple_error_message_box(
                       "An error occurred while writing to the file \"%s\": %s.",
                       out_filename, wtap_strerror(write_err));
+        g_free(display_basename);
         break;
       }
     } else {
@@ -1488,8 +1612,8 @@ 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;
+  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) {
@@ -1510,18 +1634,10 @@ cf_filter_packets(capture_file *cf, gchar *dftext, gboolean force)
     dftext = g_strdup(dftext);
     if (!dfilter_compile(dftext, &dfcode)) {
       /* 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);
-      simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
-          "%s%s%s\n"
-          "\n"
-          "The following display filter isn't a valid display filter:\n%s\n"
+      simple_message_box(ESD_TYPE_ERROR, NULL,
           "See the help for a description of the display filter syntax.",
-          simple_dialog_primary_start(), safe_dfilter_error_msg,
-          simple_dialog_primary_end(), safe_dftext);
-      g_free(safe_dfilter_error_msg);
-      g_free(safe_dftext);
+          "\"%s\" isn't a valid display filter: %s",
+          dftext, dfilter_error_msg);
       g_free(dftext);
       return CF_ERROR;
     }
@@ -1557,7 +1673,6 @@ cf_filter_packets(capture_file *cf, gchar *dftext, gboolean force)
 void
 cf_reftime_packets(capture_file *cf)
 {
-
   ref_time_packets(cf);
 }
 
@@ -1571,9 +1686,9 @@ gboolean
 cf_read_frame_r(capture_file *cf, frame_data *fdata,
                 union wtap_pseudo_header *pseudo_header, guint8 *pd)
 {
-  int err;
+  int    err;
   gchar *err_info;
-  char errmsg_errno[1024+1];
+  gchar *display_basename;
 
 #ifdef WANT_PACKET_EDITOR
   /* if fdata->file_off == -1 it means packet was edited, and we must find data inside edited_frames tree */
@@ -1581,7 +1696,7 @@ cf_read_frame_r(capture_file *cf, frame_data *fdata,
     const modified_frame_data *frame = (const modified_frame_data *) g_tree_lookup(cf->edited_frames, GINT_TO_POINTER(fdata->num));
 
     if (!frame) {
-      simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "fdata->file_off == -1, but can't find modified frame!");
+      simple_error_message_box("fdata->file_off == -1, but can't find modified frame!");
       return FALSE;
     }
 
@@ -1593,29 +1708,28 @@ cf_read_frame_r(capture_file *cf, frame_data *fdata,
 
   if (!wtap_seek_read(cf->wth, fdata->file_off, pseudo_header, pd,
                       fdata->cap_len, &err, &err_info)) {
+    display_basename = g_filename_display_basename(cf->filename);
     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);
+      simple_error_message_box("The file \"%s\" has a packet with a network type that Wireshark doesn't support.\n(%s)",
+                 display_basename, err_info);
       g_free(err_info);
       break;
 
     case WTAP_ERR_BAD_FILE:
-      g_snprintf(errmsg_errno, sizeof(errmsg_errno),
-                 "An error occurred while reading from the file \"%%s\": %s.\n(%s)",
-                 wtap_strerror(err), err_info);
+      simple_error_message_box("An error occurred while reading from the file \"%s\": %s.\n(%s)",
+                 display_basename, 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));
+      simple_error_message_box(
+                 "An error occurred while reading from the file \"%s\": %s.",
+                 display_basename, wtap_strerror(err));
       break;
     }
-    simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, errmsg_errno, cf->filename);
+    g_free(display_basename);
     return FALSE;
   }
   return TRUE;
@@ -1659,11 +1773,11 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item,
   gchar       status_str[100];
   int         progbar_nextstep;
   int         progbar_quantum;
-  dfilter_t   *dfcode;
+  dfilter_t  *dfcode;
   gboolean    filtering_tap_listeners;
   guint       tap_flags;
   gboolean    add_to_packet_list = FALSE;
-  gboolean compiled;
+  gboolean    compiled;
 
   /* Compile the current display filter.
    * We assume this will not fail since cf->dfilter is only set in
@@ -1690,7 +1804,7 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item,
 
   /* Freeze the packet list while we redo it, so we don't get any
      screen updates while it happens. */
-  new_packet_list_freeze();
+  packet_list_freeze();
 
   if (redissect) {
     /* We need to re-initialize all the state information that protocols
@@ -1709,7 +1823,7 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item,
 
     /* We need to redissect the packets so we have to discard our old
      * packet list store. */
-    new_packet_list_clear();
+    packet_list_clear();
     add_to_packet_list = TRUE;
   }
 
@@ -1724,8 +1838,8 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item,
      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);
+  prev_dis = NULL;
+  prev_cap = NULL;
   cum_bytes = 0;
 
   /* Update the progress bar when it gets to this value. */
@@ -1761,7 +1875,7 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item,
        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,
+      progbar = delayed_create_progress_dlg(cf->window, action, action_item, TRUE,
                                             &stop_flag, &start_time,
                                             progbar_val);
 
@@ -1814,7 +1928,7 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item,
     }
 
     if (redissect || refilter) {
-      /* If we're redissecting or refiltering then any frame dependencies 
+      /* If we're redissecting or refiltering then any frame dependencies
        * from the previous dissection/filtering are no longer valid.
        */
       fdata->flags.dependent_of_displayed = 0;
@@ -1882,12 +1996,12 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item,
 
   /* Unfreeze the packet list. */
   if (!add_to_packet_list)
-    new_packet_list_recreate_visible_rows();
+    packet_list_recreate_visible_rows();
 
   /* Compute the time it took to filter the file */
   compute_elapsed(&start_time);
 
-  new_packet_list_thaw();
+  packet_list_thaw();
 
   if (selected_frame_num == -1) {
     /* The selected frame didn't pass the filter. */
@@ -1935,16 +2049,15 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item,
     /* 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();
+      packet_list_select_first_row();
     }else{
-      if (!new_packet_list_select_row_from_data(selected_frame)) {
+      if (!packet_list_select_row_from_data(selected_frame)) {
         /* We didn't find a row corresponding to this frame.
            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 dissected.",
-                      simple_dialog_primary_start(), simple_dialog_primary_end());
+        simple_message_box(ESD_TYPE_INFO, NULL,
+                           "The capture file is probably not fully dissected.",
+                           "End of capture exceeded!");
       }
     }
   }
@@ -1962,11 +2075,11 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item,
 static void
 ref_time_packets(capture_file *cf)
 {
-  guint32 framenum;
+  guint32     framenum;
   frame_data *fdata;
 
   nstime_set_unset(&first_ts);
-  nstime_set_unset(&prev_dis_ts);
+  prev_dis = NULL;
   cum_bytes = 0;
 
   for (framenum = 1; framenum <= cf->count; framenum++) {
@@ -1987,7 +2100,7 @@ ref_time_packets(capture_file *cf)
     }
       /* if this frames is marked as a reference time frame, reset
         firstsec and firstusec to this frame */
-    if(fdata->flags.ref_time){
+    if (fdata->flags.ref_time) {
         first_ts = fdata->abs_ts;
     }
 
@@ -1995,8 +2108,8 @@ ref_time_packets(capture_file *cf)
      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;
+    if (prev_dis == NULL) {
+        prev_dis = fdata;
     }
 
     /* Get the time elapsed between the first packet and this packet. */
@@ -2012,19 +2125,19 @@ ref_time_packets(capture_file *cf)
 
     /* If this frame is displayed, get the time elapsed between the
      previous displayed packet and this packet. */
-    if( fdata->flags.passed_dfilter ) {
-        nstime_delta(&fdata->del_dis_ts, &fdata->abs_ts, &prev_dis_ts);
-        prev_dis_ts = fdata->abs_ts;
+    if ( fdata->flags.passed_dfilter ) {
+        fdata->prev_dis = prev_dis;
+        prev_dis = fdata;
     }
 
     /*
      * Byte counts
      */
-    if( (fdata->flags.passed_dfilter) || (fdata->flags.ref_time) ){
+    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 (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;
@@ -2049,21 +2162,22 @@ process_specified_packets(capture_file *cf, packet_range_t *range,
                          union wtap_pseudo_header *, const guint8 *, void *),
     void *callback_args)
 {
-  guint32 framenum;
-  frame_data *fdata;
   union wtap_pseudo_header pseudo_header;
-  guint8      pd[WTAP_MAX_PACKET_SIZE+1];
-  psp_return_t ret = PSP_FINISHED;
 
-  progdlg_t  *progbar = NULL;
-  int         progbar_count;
-  float       progbar_val;
-  gboolean    progbar_stop_flag;
-  GTimeVal    progbar_start_time;
-  gchar       progbar_status_str[100];
-  int         progbar_nextstep;
-  int         progbar_quantum;
-  range_process_e process_this;
+  guint32          framenum;
+  frame_data      *fdata;
+  guint8           pd[WTAP_MAX_PACKET_SIZE+1];
+  psp_return_t     ret     = PSP_FINISHED;
+
+  progdlg_t       *progbar = NULL;
+  int              progbar_count;
+  float            progbar_val;
+  gboolean         progbar_stop_flag;
+  GTimeVal         progbar_start_time;
+  gchar            progbar_status_str[100];
+  int              progbar_nextstep;
+  int              progbar_quantum;
+  range_process_e  process_this;
 
   /* Update the progress bar when it gets to this value. */
   progbar_nextstep = 0;
@@ -2078,7 +2192,8 @@ process_specified_packets(capture_file *cf, packet_range_t *range,
   progbar_stop_flag = FALSE;
   g_get_current_time(&progbar_start_time);
 
-  packet_range_process_init(range);
+  if (range != NULL)
+    packet_range_process_init(range);
 
   /* Iterate through all the packets, printing the packets that
      were selected by the current display filter.  */
@@ -2091,7 +2206,7 @@ process_specified_packets(capture_file *cf, packet_range_t *range,
        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(string1, string2,
+      progbar = delayed_create_progress_dlg(cf->window, string1, string2,
                                             terminate_is_stop,
                                             &progbar_stop_flag,
                                             &progbar_start_time,
@@ -2128,14 +2243,16 @@ process_specified_packets(capture_file *cf, packet_range_t *range,
 
     progbar_count++;
 
-    /* do we have to process this packet? */
-    process_this = packet_range_process_packet(range, fdata);
-    if (process_this == range_process_next) {
+    if (range != NULL) {
+      /* do we have to process this packet? */
+      process_this = packet_range_process_packet(range, fdata);
+      if (process_this == range_process_next) {
         /* this packet uninteresting, continue with next one */
         continue;
-    } else if (process_this == range_processing_finished) {
+      } else if (process_this == range_processing_finished) {
         /* all interesting packets processed, stop the loop */
         break;
+      }
     }
 
     /* Get the packet */
@@ -2161,7 +2278,7 @@ process_specified_packets(capture_file *cf, packet_range_t *range,
 }
 
 typedef struct {
-  gboolean construct_protocol_tree;
+  gboolean     construct_protocol_tree;
   column_info *cinfo;
 } retap_callback_args_t;
 
@@ -2171,7 +2288,7 @@ 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;
 
   epan_dissect_init(&edt, args->construct_protocol_tree, FALSE);
   tap_queue_init(&edt);
@@ -2185,10 +2302,10 @@ retap_packet(capture_file *cf _U_, frame_data *fdata,
 cf_read_status_t
 cf_retap_packets(capture_file *cf)
 {
-  packet_range_t range;
+  packet_range_t        range;
   retap_callback_args_t callback_args;
-  gboolean filtering_tap_listeners;
-  guint tap_flags;
+  gboolean              filtering_tap_listeners;
+  guint                 tap_flags;
 
   /* Do we have any tap listeners with filters? */
   filtering_tap_listeners = have_filtering_tap_listeners();
@@ -2241,6 +2358,8 @@ typedef struct {
   char         *line_buf;
   int           line_buf_len;
   gint         *col_widths;
+  int           num_visible_cols;
+  gint         *visible_cols;
 } print_callback_args_t;
 
 static gboolean
@@ -2249,15 +2368,15 @@ 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.
@@ -2299,9 +2418,9 @@ print_packet(capture_file *cf, frame_data *fdata,
     }
     cp = &args->line_buf[0];
     line_len = 0;
-    for (i = 0; i < cf->cinfo.num_cols; i++) {
+    for (i = 0; i < args->num_visible_cols; i++) {
       /* Find the length of the string for this column. */
-      column_len = (int) strlen(cf->cinfo.col_data[i]);
+      column_len = (int) strlen(cf->cinfo.col_data[args->visible_cols[i]]);
       if (args->col_widths[i] > column_len)
          column_len = args->col_widths[i];
 
@@ -2316,12 +2435,12 @@ print_packet(capture_file *cf, frame_data *fdata,
       }
 
       /* Right-justify the packet number column. */
-      if (cf->cinfo.col_fmt[i] == COL_NUMBER)
-        g_snprintf(cp, column_len+1, "%*s", args->col_widths[i], cf->cinfo.col_data[i]);
+      if (cf->cinfo.col_fmt[args->visible_cols[i]] == COL_NUMBER)
+        g_snprintf(cp, column_len+1, "%*s", args->col_widths[i], cf->cinfo.col_data[args->visible_cols[i]]);
       else
-        g_snprintf(cp, column_len+1, "%-*s", args->col_widths[i], cf->cinfo.col_data[i]);
+        g_snprintf(cp, column_len+1, "%-*s", args->col_widths[i], cf->cinfo.col_data[args->visible_cols[i]]);
       cp += column_len;
-      if (i != cf->cinfo.num_cols - 1)
+      if (i != args->num_visible_cols - 1)
         *cp++ = ' ';
     }
     *cp = '\0';
@@ -2379,7 +2498,7 @@ print_packet(capture_file *cf, frame_data *fdata,
   epan_dissect_cleanup(&edt);
 
   /* do we want to have a formfeed between each packet from now on? */
-  if(args->print_args->print_formfeed) {
+  if (args->print_args->print_formfeed) {
     args->print_formfeed = TRUE;
   }
 
@@ -2393,14 +2512,14 @@ fail:
 cf_print_status_t
 cf_print_packets(capture_file *cf, print_args_t *print_args)
 {
-  int         i;
   print_callback_args_t callback_args;
-  gint        data_width;
-  char        *cp;
-  int         cp_off;
-  int         column_len;
-  int         line_len;
-  psp_return_t ret;
+  gint          data_width;
+  char         *cp;
+  int           i, cp_off, column_len, line_len;
+  int           num_visible_col = 0, last_visible_col = 0, visible_col_count;
+  psp_return_t  ret;
+  GList        *clp;
+  fmt_data     *cfmt;
 
   callback_args.print_args = print_args;
   callback_args.print_header_line = TRUE;
@@ -2411,6 +2530,8 @@ cf_print_packets(capture_file *cf, print_args_t *print_args)
   callback_args.line_buf = NULL;
   callback_args.line_buf_len = 256;
   callback_args.col_widths = NULL;
+  callback_args.num_visible_cols = 0;
+  callback_args.visible_cols = NULL;
 
   if (!print_preamble(print_args->stream, cf->filename)) {
     destroy_print_stream(print_args->stream);
@@ -2422,27 +2543,56 @@ cf_print_packets(capture_file *cf, print_args_t *print_args)
        and get the column widths. */
     callback_args.header_line_buf = g_malloc(callback_args.header_line_buf_len + 1);
 
+    /* Find the number of visible columns and the last visible column */
+    for (i = 0; i < prefs.num_cols; i++) {
+
+        clp = g_list_nth(prefs.col_list, i);
+        if (clp == NULL) /* Sanity check, Invalid column requested */
+            continue;
+
+        cfmt = (fmt_data *) clp->data;
+        if (cfmt->visible) {
+            num_visible_col++;
+            last_visible_col = i;
+        }
+    }
+
     /* Find the widths for each of the columns - maximum of the
        width of the title and the width of the data - and construct
        a buffer with a line containing the column titles. */
-    callback_args.col_widths = (gint *) g_malloc(sizeof(gint) * cf->cinfo.num_cols);
+    callback_args.num_visible_cols = num_visible_col;
+    callback_args.col_widths = (gint *) g_malloc(sizeof(gint) * num_visible_col);
+    callback_args.visible_cols = (gint *) g_malloc(sizeof(gint) * num_visible_col);
     cp = &callback_args.header_line_buf[0];
     line_len = 0;
+    visible_col_count = 0;
     for (i = 0; i < cf->cinfo.num_cols; i++) {
+
+      clp = g_list_nth(prefs.col_list, i);
+      if (clp == NULL) /* Sanity check, Invalid column requested */
+          continue;
+
+      cfmt = (fmt_data *) clp->data;
+      if (cfmt->visible == FALSE)
+          continue;
+
+      /* Save the order of visible columns */
+      callback_args.visible_cols[visible_col_count] = i;
+
       /* Don't pad the last column. */
-      if (i == cf->cinfo.num_cols - 1)
-        callback_args.col_widths[i] = 0;
+      if (i == last_visible_col)
+        callback_args.col_widths[visible_col_count] = 0;
       else {
-        callback_args.col_widths[i] = (gint) strlen(cf->cinfo.col_title[i]);
+        callback_args.col_widths[visible_col_count] = (gint) strlen(cf->cinfo.col_title[i]);
         data_width = get_column_char_width(get_column_format(i));
-        if (data_width > callback_args.col_widths[i])
-          callback_args.col_widths[i] = data_width;
+        if (data_width > callback_args.col_widths[visible_col_count])
+          callback_args.col_widths[visible_col_count] = data_width;
       }
 
       /* Find the length of the string for this column. */
       column_len = (int) strlen(cf->cinfo.col_title[i]);
       if (callback_args.col_widths[i] > column_len)
-        column_len = callback_args.col_widths[i];
+        column_len = callback_args.col_widths[visible_col_count];
 
       /* Make sure there's room in the line buffer for the column; if not,
          double its length. */
@@ -2457,12 +2607,14 @@ cf_print_packets(capture_file *cf, print_args_t *print_args)
 
       /* Right-justify the packet number column. */
 /*      if (cf->cinfo.col_fmt[i] == COL_NUMBER)
-        g_snprintf(cp, column_len+1, "%*s", callback_args.col_widths[i], cf->cinfo.col_title[i]);
+        g_snprintf(cp, column_len+1, "%*s", callback_args.col_widths[visible_col_count], cf->cinfo.col_title[i]);
       else*/
-      g_snprintf(cp, column_len+1, "%-*s", callback_args.col_widths[i], cf->cinfo.col_title[i]);
+      g_snprintf(cp, column_len+1, "%-*s", callback_args.col_widths[visible_col_count], cf->cinfo.col_title[i]);
       cp += column_len;
       if (i != cf->cinfo.num_cols - 1)
         *cp++ = ' ';
+
+      visible_col_count++;
     }
     *cp = '\0';
 
@@ -2481,6 +2633,7 @@ cf_print_packets(capture_file *cf, print_args_t *print_args)
   g_free(callback_args.header_line_buf);
   g_free(callback_args.line_buf);
   g_free(callback_args.col_widths);
+  g_free(callback_args.visible_cols);
 
   switch (ret) {
 
@@ -2524,8 +2677,8 @@ write_pdml_packet(capture_file *cf _U_, frame_data *fdata,
                   union wtap_pseudo_header *pseudo_header, const guint8 *pd,
           void *argsp)
 {
-  FILE *fh = argsp;
-  epan_dissect_t edt;
+  FILE           *fh = argsp;
+  epan_dissect_t  edt;
 
   /* Create the protocol tree, but don't fill in the column information. */
   epan_dissect_init(&edt, TRUE, TRUE);
@@ -2542,8 +2695,8 @@ write_pdml_packet(capture_file *cf _U_, frame_data *fdata,
 cf_print_status_t
 cf_write_pdml_packets(capture_file *cf, print_args_t *print_args)
 {
-  FILE        *fh;
-  psp_return_t ret;
+  FILE         *fh;
+  psp_return_t  ret;
 
   fh = ws_fopen(print_args->file, "w");
   if (fh == NULL)
@@ -2594,9 +2747,9 @@ write_psml_packet(capture_file *cf, frame_data *fdata,
                   union wtap_pseudo_header *pseudo_header, const guint8 *pd,
           void *argsp)
 {
-  FILE *fh = argsp;
-  epan_dissect_t edt;
-  gboolean proto_tree_needed;
+  FILE           *fh = argsp;
+  epan_dissect_t  edt;
+  gboolean        proto_tree_needed;
 
   /* Fill in the column information, only create the protocol tree
      if having custom columns. */
@@ -2617,8 +2770,8 @@ write_psml_packet(capture_file *cf, frame_data *fdata,
 cf_print_status_t
 cf_write_psml_packets(capture_file *cf, print_args_t *print_args)
 {
-  FILE        *fh;
-  psp_return_t ret;
+  FILE         *fh;
+  psp_return_t  ret;
 
   fh = ws_fopen(print_args->file, "w");
   if (fh == NULL)
@@ -2669,9 +2822,9 @@ write_csv_packet(capture_file *cf, frame_data *fdata,
                  union wtap_pseudo_header *pseudo_header, const guint8 *pd,
                  void *argsp)
 {
-  FILE *fh = argsp;
-  epan_dissect_t edt;
-  gboolean proto_tree_needed;
+  FILE           *fh = argsp;
+  epan_dissect_t  edt;
+  gboolean        proto_tree_needed;
 
   /* Fill in the column information, only create the protocol tree
      if having custom columns. */
@@ -2692,8 +2845,8 @@ write_csv_packet(capture_file *cf, frame_data *fdata,
 cf_print_status_t
 cf_write_csv_packets(capture_file *cf, print_args_t *print_args)
 {
-  FILE        *fh;
-  psp_return_t ret;
+  FILE         *fh;
+  psp_return_t  ret;
 
   fh = ws_fopen(print_args->file, "w");
   if (fh == NULL)
@@ -2744,8 +2897,8 @@ write_carrays_packet(capture_file *cf _U_, frame_data *fdata,
              union wtap_pseudo_header *pseudo_header,
              const guint8 *pd, void *argsp)
 {
-  FILE *fh = argsp;
-  epan_dissect_t edt;
+  FILE           *fh = argsp;
+  epan_dissect_t  edt;
 
   epan_dissect_init(&edt, TRUE, TRUE);
   epan_dissect_run(&edt, pseudo_header, pd, fdata, NULL);
@@ -2758,8 +2911,8 @@ write_carrays_packet(capture_file *cf _U_, frame_data *fdata,
 cf_print_status_t
 cf_write_carrays_packets(capture_file *cf, print_args_t *print_args)
 {
-  FILE        *fh;
-  psp_return_t ret;
+  FILE         *fh;
+  psp_return_t  ret;
 
   fh = ws_fopen(print_args->file, "w");
 
@@ -2807,7 +2960,7 @@ gboolean
 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);
@@ -2829,8 +2982,8 @@ cf_find_string_protocol_tree(capture_file *cf, proto_tree *tree,  match_data *md
 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)) {
@@ -2854,19 +3007,20 @@ match_protocol_tree(capture_file *cf, frame_data *fdata, void *criterion)
 static void
 match_subtree_text(proto_node *node, gpointer data)
 {
-  match_data    *mdata = (match_data *) data;
-  const gchar   *string = mdata->string;
+  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);
+  capture_file *cf         = mdata->cf;
+  field_info   *fi         = PNODE_FINFO(node);
   gchar         label_str[ITEM_LABEL_LENGTH];
-  gchar         *label_ptr;
+  gchar        *label_ptr;
   size_t        label_len;
   guint32       i;
   guint8        c_char;
-  size_t        c_match = 0;
+  size_t        c_match    = 0;
 
-  g_assert(fi && "dissection with an invisible proto tree?");
+  /* dissection with an invisible proto tree? */
+  g_assert(fi);
 
   if (mdata->frame_matched) {
     /* We already had a match; don't bother doing any more work. */
@@ -2913,7 +3067,7 @@ gboolean
 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);
@@ -2923,17 +3077,17 @@ cf_find_packet_summary_line(capture_file *cf, const char *string,
 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;
-  match_result      result = MR_NOTMATCHED;
-  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)) {
@@ -2974,7 +3128,7 @@ match_summary_line(capture_file *cf, frame_data *fdata, void *criterion)
 
 typedef struct {
     const guint8 *data;
-    size_t data_len;
+    size_t        data_len;
 } cbs_t;    /* "Counted byte string" */
 
 gboolean
@@ -3011,14 +3165,14 @@ cf_find_packet_data(capture_file *cf, const guint8 *string, size_t string_size,
 static match_result
 match_ascii_and_unicode(capture_file *cf, frame_data *fdata, void *criterion)
 {
-  cbs_t        *info = criterion;
+  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;
+  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)) {
@@ -3057,14 +3211,14 @@ 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)
 {
-  cbs_t        *info = criterion;
+  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;
+  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)) {
@@ -3102,14 +3256,14 @@ match_ascii(capture_file *cf, frame_data *fdata, void *criterion)
 static match_result
 match_unicode(capture_file *cf, frame_data *fdata, void *criterion)
 {
-  cbs_t        *info = criterion;
+  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;
+  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)) {
@@ -3147,13 +3301,13 @@ match_unicode(capture_file *cf, frame_data *fdata, void *criterion)
 static match_result
 match_binary(capture_file *cf, frame_data *fdata, void *criterion)
 {
-  cbs_t        *info = criterion;
+  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;
+  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)) {
@@ -3196,7 +3350,7 @@ cf_find_packet_dfilter_string(capture_file *cf, const char *filter,
                               search_direction dir)
 {
   dfilter_t *sfcode;
-  gboolean result;
+  gboolean   result;
 
   if (!dfilter_compile(filter, &sfcode)) {
      /*
@@ -3221,8 +3375,8 @@ static match_result
 match_dfilter(capture_file *cf, frame_data *fdata, void *criterion)
 {
   dfilter_t      *sfcode = criterion;
-  epan_dissect_t edt;
-  match_result   result;
+  epan_dissect_t  edt;
+  match_result    result;
 
   /* Load the frame's data. */
   if (!cf_read_frame(cf, fdata)) {
@@ -3310,7 +3464,7 @@ find_packet(capture_file *cf,
          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("Searching", title,
+         progbar = delayed_create_progress_dlg(cf->window, "Searching", title,
            FALSE, &stop_flag, &start_time, progbar_val);
 
       /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
@@ -3418,17 +3572,16 @@ find_packet(capture_file *cf,
   if (new_fd != NULL) {
     /* Find and select */
     cf->search_in_progress = TRUE;
-    found = new_packet_list_select_row_from_data(new_fd);
+    found = packet_list_select_row_from_data(new_fd);
     cf->search_in_progress = FALSE;
     cf->search_pos = 0; /* Reset the position */
     if (!found) {
       /* We didn't find a row corresponding to this frame.
          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 dissected.",
-                    simple_dialog_primary_start(), simple_dialog_primary_end());
+      simple_message_box(ESD_TYPE_INFO, NULL,
+                         "The capture file is probably not fully dissected.",
+                         "End of capture exceeded!");
       return FALSE;
     }
     return TRUE;    /* success */
@@ -3455,14 +3608,13 @@ cf_goto_frame(capture_file *cf, guint fnumber)
     return FALSE;   /* we failed to go to that packet */
   }
 
-  if (!new_packet_list_select_row_from_data(fdata)) {
+  if (!packet_list_select_row_from_data(fdata)) {
     /* We didn't find a row corresponding to this frame.
        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 dissected.",
-                  simple_dialog_primary_start(), simple_dialog_primary_end());
+    simple_message_box(ESD_TYPE_INFO, NULL,
+                       "The capture file is probably not fully dissected.",
+                       "End of capture exceeded!");
     return FALSE;
   }
   return TRUE;  /* we got to that packet */
@@ -3472,7 +3624,7 @@ gboolean
 cf_goto_top_frame(void)
 {
   /* Find and select */
-  new_packet_list_select_first_row();
+  packet_list_select_first_row();
   return TRUE;  /* we got to that packet */
 }
 
@@ -3480,7 +3632,7 @@ gboolean
 cf_goto_bottom_frame(void)
 {
   /* Find and select */
-  new_packet_list_select_last_row();
+  packet_list_select_last_row();
   return TRUE;  /* we got to that packet */
 }
 
@@ -3490,8 +3642,8 @@ cf_goto_bottom_frame(void)
 gboolean
 cf_goto_framenum(capture_file *cf)
 {
-  header_field_info       *hfinfo;
-  guint32                 framenum;
+  header_field_info *hfinfo;
+  guint32            framenum;
 
   if (cf->finfo_selected) {
     hfinfo = cf->finfo_selected->hfinfo;
@@ -3510,10 +3662,11 @@ cf_goto_framenum(capture_file *cf)
 void
 cf_select_packet(capture_file *cf, int row)
 {
-  frame_data *fdata;
+  epan_dissect_t *old_edt;
+  frame_data     *fdata;
 
   /* Get the frame data struct pointer for this frame */
-  fdata = new_packet_list_get_row_data(row);
+  fdata = packet_list_get_row_data(row);
 
   if (fdata == NULL) {
     /* XXX - if a GtkCList's selection mode is GTK_SELECTION_BROWSE, when
@@ -3560,10 +3713,8 @@ cf_select_packet(capture_file *cf, int row)
   cf->current_frame = fdata;
   cf->current_row = row;
 
+  old_edt = cf->edt;
   /* Create the logical protocol tree. */
-  if (cf->edt != NULL)
-    epan_dissect_free(cf->edt);
-
   /* We don't need the columns here. */
   cf->edt = epan_dissect_new(TRUE, TRUE);
 
@@ -3574,17 +3725,19 @@ cf_select_packet(capture_file *cf, int row)
   dfilter_macro_build_ftv_cache(cf->edt->tree);
 
   cf_callback_invoke(cf_cb_packet_selected, cf);
+
+  if (old_edt != NULL)
+    epan_dissect_free(old_edt);
+
 }
 
 /* Unselect the selected packet, if any. */
 void
 cf_unselect_packet(capture_file *cf)
 {
-  /* Destroy the epan_dissect_t for the unselected packet. */
-  if (cf->edt != NULL) {
-    epan_dissect_free(cf->edt);
-    cf->edt = NULL;
-  }
+  epan_dissect_t *old_edt = cf->edt;
+
+  cf->edt = NULL;
 
   /* No packet is selected. */
   cf->current_frame = NULL;
@@ -3594,6 +3747,10 @@ cf_unselect_packet(capture_file *cf)
 
   /* No protocol tree means no selected field. */
   cf_unselect_field(cf);
+
+  /* Destroy the epan_dissect_t for the unselected packet. */
+  if (old_edt != NULL)
+    epan_dissect_free(old_edt);
 }
 
 /* Unset the selected protocol tree field, if any. */
@@ -3665,11 +3822,11 @@ const gchar *
 cf_read_shb_comment(capture_file *cf)
 {
   wtapng_section_t *shb_inf;
-  const gchar *temp_str;
+  const gchar      *temp_str;
 
   /* Get info from SHB */
   shb_inf = wtap_file_get_shb_info(cf->wth);
-  if(shb_inf == NULL)
+  if (shb_inf == NULL)
         return NULL;
   temp_str = shb_inf->opt_comment;
   g_free(shb_inf);
@@ -3690,16 +3847,47 @@ cf_update_capture_comment(capture_file *cf, gchar *comment)
   if (shb_inf && shb_inf->opt_comment) {
     if (strcmp(shb_inf->opt_comment, comment) == 0) {
       g_free(comment);
+      g_free(shb_inf);
       return;
     }
   }
 
+  g_free(shb_inf);
+
   /* The comment has changed, let's update it */
   wtap_write_shb_comment(cf->wth, comment);
   /* Mark the file as having unsaved changes */
   cf->unsaved_changes = TRUE;
 }
 
+void
+cf_update_packet_comment(capture_file *cf, frame_data *fdata, gchar *comment)
+{
+  if (fdata->opt_comment != NULL) {
+    /* OK, remove the old comment. */
+    g_free(fdata->opt_comment);
+    fdata->opt_comment = NULL;
+    cf->packet_comment_count--;
+  }
+  if (comment != NULL) {
+    /* Add the new comment. */
+    fdata->opt_comment = comment;
+    cf->packet_comment_count++;
+  }
+
+  /* OK, we have unsaved changes. */
+  cf->unsaved_changes = TRUE;
+}
+
+/*
+ * Does this capture file have any comments?
+ */
+gboolean
+cf_has_comments(capture_file *cf)
+{
+  return (cf_read_shb_comment(cf) != NULL || cf->packet_comment_count != 0);
+}
+
 typedef struct {
   wtap_dumper *pdh;
   const char  *fname;
@@ -3719,8 +3907,9 @@ save_packet(capture_file *cf _U_, frame_data *fdata,
             void *argsp)
 {
   save_callback_args_t *args = argsp;
-  struct wtap_pkthdr hdr;
+  struct wtap_pkthdr    hdr;
   int           err;
+  gchar        *display_basename;
 
   /* init the wtap header for saving */
   /* XXX - these are the only flags that correspond to data that we have
@@ -3763,15 +3952,17 @@ save_packet(capture_file *cf _U_, frame_data *fdata,
          * This is a problem with the particular frame we're writing;
          * note that, and give the frame number.
          */
-        simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
+        simple_error_message_box(
                       "Frame %u has a network type that can't be saved in a \"%s\" file.",
                       fdata->num, wtap_file_type_string(args->file_type));
         break;
 
       default:
-        simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
+        display_basename = g_filename_display_basename(args->fname);
+        simple_error_message_box(
                       "An error occurred while writing to the file \"%s\": %s.",
-                      args->fname, wtap_strerror(err));
+                      display_basename, wtap_strerror(err));
+        g_free(display_basename);
         break;
       }
     } else {
@@ -3784,18 +3975,19 @@ save_packet(capture_file *cf _U_, frame_data *fdata,
 }
 
 /*
- * Can this capture file be saved in any format except by copying the raw data?
+ * Can this capture file be written out in any format using Wiretap
+ * rather than by copying the raw data?
  */
 gboolean
-cf_can_save_as(capture_file *cf)
+cf_can_write_with_wiretap(capture_file *cf)
 {
   int ft;
 
   for (ft = 0; ft < WTAP_NUM_FILE_TYPES; ft++) {
     /* To save a file with Wiretap, Wiretap has to handle that format,
        and its code to handle that format must be able to write a file
-       with this file's encapsulation type. */
-    if (wtap_dump_can_open(ft) && wtap_dump_can_write_encap(ft, cf->lnk_t)) {
+       with this file's encapsulation types. */
+    if (wtap_dump_can_write_encaps(ft, cf->linktypes)) {
       /* OK, we can write it out in this type. */
       return TRUE;
     }
@@ -3805,48 +3997,301 @@ cf_can_save_as(capture_file *cf)
   return FALSE;
 }
 
-cf_status_t
-cf_save(capture_file *cf, const char *fname, packet_range_t *range, guint save_format, gboolean compressed)
+/*
+ * Quick scan to find packet offsets.
+ */
+static cf_read_status_t
+rescan_file(capture_file *cf, const char *fname, gboolean is_tempfile, int *err)
 {
-  gchar        *from_filename;
+  const struct wtap_pkthdr *phdr;
+  gchar               *err_info;
+  gchar               *name_ptr;
+  gint64               data_offset;
+  gint64               file_pos;
+  progdlg_t *volatile  progbar        = NULL;
+  gboolean             stop_flag;
+  volatile gint64      size;
+  volatile float       progbar_val;
+  GTimeVal             start_time;
+  gchar                status_str[100];
+  volatile gint64      progbar_nextstep;
+  volatile gint64      progbar_quantum;
+  guint32              framenum;
+  frame_data          *fdata;
+  volatile int         count          = 0;
+#ifdef HAVE_LIBPCAP
+  volatile int         displayed_once = 0;
+#endif
+
+  /* Close the old handle. */
+  wtap_close(cf->wth);
+
+  /* Open the new file. */
+  cf->wth = wtap_open_offline(fname, err, &err_info, TRUE);
+  if (cf->wth == NULL) {
+    cf_open_failure_alert_box(fname, *err, err_info, FALSE, 0);
+    return CF_READ_ERROR;
+  }
+
+  /* We're scanning a file whose contents should be the same as what
+     we had before, so we don't discard dissection state etc.. */
+  cf->f_datalen = 0;
+
+  /* Set the file name because we need it to set the follow stream filter.
+     XXX - is that still true?  We need it for other reasons, though,
+     in any case. */
+  cf->filename = g_strdup(fname);
+
+  /* Indicate whether it's a permanent or temporary file. */
+  cf->is_tempfile = is_tempfile;
+
+  /* No user changes yet. */
+  cf->unsaved_changes = FALSE;
+
+  cf->cd_t        = wtap_file_type(cf->wth);
+  cf->linktypes = g_array_sized_new(FALSE, FALSE, (guint) sizeof(int), 1);
+
+  cf->snap      = wtap_snapshot_length(cf->wth);
+  if (cf->snap == 0) {
+    /* Snapshot length not known. */
+    cf->has_snap = FALSE;
+    cf->snap = WTAP_MAX_PACKET_SIZE;
+  } else
+    cf->has_snap = TRUE;
+
+  name_ptr = g_filename_display_basename(cf->filename);
+
+  cf_callback_invoke(cf_cb_file_rescan_started, cf);
+
+  /* Record whether the file is compressed.
+     XXX - do we know this at open time? */
+  cf->iscompressed = wtap_iscompressed(cf->wth);
+
+  /* Find the size of the file. */
+  size = wtap_file_size(cf->wth, NULL);
+
+  /* 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. */
+  if (size >= 0) {
+    progbar_quantum = size/N_PROGBAR_UPDATES;
+    if (progbar_quantum < MIN_QUANTUM)
+      progbar_quantum = MIN_QUANTUM;
+  }else
+    progbar_quantum = 0;
+  /* Progress so far. */
+  progbar_val = 0.0f;
+
+  stop_flag = FALSE;
+  g_get_current_time(&start_time);
+
+  framenum = 0;
+  phdr = wtap_phdr(cf->wth);
+  while ((wtap_read(cf->wth, err, &err_info, &data_offset))) {
+    framenum++;
+    fdata = frame_data_sequence_find(cf->frames, framenum);
+    fdata->file_off = data_offset;
+    if (size >= 0) {
+      count++;
+      file_pos = wtap_read_so_far(cf->wth);
+
+      /* Create the progress bar if necessary.
+       * 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, file_pos, status_str, sizeof(status_str));
+        progbar = delayed_create_progress_dlg(cf->window, "Rescanning", name_ptr,
+                                              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 (file_pos >= progbar_nextstep) {
+        if (progbar != NULL) {
+          progbar_val = calc_progbar_val(cf, size, file_pos, status_str, sizeof(status_str));
+          /* update the packet bar content on the first run or frequently on very large files */
+#ifdef HAVE_LIBPCAP
+          if (progbar_quantum > 500000 || displayed_once == 0) {
+            if ((auto_scroll_live || displayed_once == 0 || cf->displayed_count < 1000) && cf->count != 0) {
+              displayed_once = 1;
+              packets_bar_update();
+            }
+          }
+#endif /* HAVE_LIBPCAP */
+          update_progress_dlg(progbar, progbar_val, status_str);
+        }
+        progbar_nextstep += progbar_quantum;
+      }
+    }
+
+    if (stop_flag) {
+      /* Well, the user decided to abort the rescan.  Sadly, as this
+         isn't a reread, recovering is difficult, so we'll just
+         close the current capture. */
+      break;
+    }
+
+    /* Add this packet's link-layer encapsulation type to cf->linktypes, if
+       it's not already there.
+       XXX - yes, this is O(N), so if every packet had a different
+       link-layer encapsulation type, it'd be O(N^2) to read the file, but
+       there are probably going to be a small number of encapsulation types
+       in a file. */
+    cf_add_encapsulation_type(cf, phdr->pkt_encap);
+  }
+
+  /* Free the display name */
+  g_free(name_ptr);
+
+  /* We're done reading the file; destroy the progress bar if it was created. */
+  if (progbar != NULL)
+    destroy_progress_dlg(progbar);
+
+  /* We're done reading sequentially through the file. */
+  cf->state = FILE_READ_DONE;
+
+  /* Close the sequential I/O side, to free up memory it requires. */
+  wtap_sequential_close(cf->wth);
+
+  /* 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
+     WTAP_ENCAP_PER_PACKET). */
+  cf->lnk_t = wtap_file_encap(cf->wth);
+
+  cf_callback_invoke(cf_cb_file_rescan_finished, cf);
+
+  if (stop_flag) {
+    /* Our caller will give up at this point. */
+    return CF_READ_ABORTED;
+  }
+
+  if (*err != 0) {
+    /* Put up a message box noting that the read failed somewhere along
+       the line.  Don't throw out the stuff we managed to read, though,
+       if any. */
+    switch (*err) {
+
+    case WTAP_ERR_UNSUPPORTED:
+      simple_error_message_box(
+                 "The capture file contains record data that Wireshark doesn't support.\n(%s)",
+                 err_info);
+      g_free(err_info);
+      break;
+
+    case WTAP_ERR_UNSUPPORTED_ENCAP:
+      simple_error_message_box(
+                 "The capture file has a packet with a network type that Wireshark doesn't support.\n(%s)",
+                 err_info);
+      g_free(err_info);
+      break;
+
+    case WTAP_ERR_CANT_READ:
+      simple_error_message_box(
+                 "An attempt to read from the capture file failed for"
+                 " some unknown reason.");
+      break;
+
+    case WTAP_ERR_SHORT_READ:
+      simple_error_message_box(
+                 "The capture file appears to have been cut short"
+                 " in the middle of a packet.");
+      break;
+
+    case WTAP_ERR_BAD_FILE:
+      simple_error_message_box(
+                 "The capture file appears to be damaged or corrupt.\n(%s)",
+                 err_info);
+      g_free(err_info);
+      break;
+
+    case WTAP_ERR_DECOMPRESS:
+      simple_error_message_box(
+                 "The compressed capture file appears to be damaged or corrupt.\n"
+                 "(%s)", err_info);
+      g_free(err_info);
+      break;
+
+    default:
+      simple_error_message_box(
+                 "An error occurred while reading the"
+                 " capture file: %s.", wtap_strerror(*err));
+      break;
+    }
+    return CF_READ_ERROR;
+  } else
+    return CF_READ_OK;
+}
+
+cf_write_status_t
+cf_save_packets(capture_file *cf, const char *fname, guint save_format,
+                gboolean compressed, gboolean discard_comments,
+                gboolean dont_reopen)
+{
+  gchar        *fname_new = NULL;
   int           err;
-  gboolean      do_copy;
+  gchar        *err_info;
+  enum {
+     SAVE_WITH_MOVE,
+     SAVE_WITH_COPY,
+     SAVE_WITH_WTAP
+  }             how_to_save;
   wtap_dumper  *pdh;
   save_callback_args_t callback_args;
+#ifdef _WIN32
+  gchar        *display_basename;
+#endif
+  guint         framenum;
+  frame_data   *fdata;
 
   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... */
-  if (file_exists(fname)) {
-    simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
-      "%sCapture file: \"%s\" already exists!%s\n\n"
-      "Please choose a different filename.",
-      simple_dialog_primary_start(), fname, simple_dialog_primary_end());
-    goto fail;
-  }
-
-  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. */
+  if (save_format == cf->cd_t && compressed == cf->iscompressed
+      && !discard_comments && !cf->unsaved_changes) {
+    /* We're saving in the format it's already in, and we're
+       not discarding comments, and there are no changes we have
+       in memory that aren't saved to the file, so we can just move
+       or copy the raw data. */
 
     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.
+         This acts as a "safe save", in that, if the file already
+         exists, the existing file will be removed only if the rename
+         succeeds.
+
+         Sadly, on Windows, as we have the current capture file
+         open, even MoveFileEx() with MOVEFILE_REPLACE_EXISTING
+         (to cause the rename to remove an existing target), as
+         done by ws_stdio_rename() (ws_rename() is #defined to
+         be ws_stdio_rename() on Windows) will fail.
+
+         According to the MSDN documentation for CreateFile(), if,
+         when we open a capture file, we were to directly do a CreateFile(),
+         opening with FILE_SHARE_DELETE|FILE_SHARE_READ, and then
+         convert it to a file descriptor with _open_osfhandle(),
+         that would allow the file to be renamed out from under us.
+
+         However, that doesn't work in practice.  Perhaps the problem
+         is that the process doing the rename is the process that
+         has the file open. */
 #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;
+        how_to_save = SAVE_WITH_MOVE;
       } else {
         if (errno == EXDEV) {
           /* They're on different file systems, so we have to copy the
              file. */
-          do_copy = TRUE;
-          from_filename = cf->filename;
+          how_to_save = SAVE_WITH_COPY;
         } else {
           /* The rename failed, but not because they're on different
              file systems - put up an error message.  (Or should we
@@ -3855,40 +4300,65 @@ cf_save(capture_file *cf, const char *fname, packet_range_t *range, guint save_f
              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);
+          cf_rename_failure_alert_box(fname, errno);
           goto fail;
         }
       }
 #else
-      do_copy = TRUE;
-      from_filename = cf->filename;
+      how_to_save = SAVE_WITH_COPY;
 #endif
     } else {
       /* It's a permanent file, so we should copy it, and not remove the
          original. */
-      do_copy = TRUE;
-      from_filename = cf->filename;
+      how_to_save = SAVE_WITH_COPY;
     }
 
-    if (do_copy) {
-      /* Copy the file, if we haven't moved it. */
-      if (!copy_file_binary_mode(from_filename, fname))
-        goto fail;
+    if (how_to_save == SAVE_WITH_COPY) {
+      /* Copy the file, if we haven't moved it.  If we're overwriting
+         an existing file, we do it with a "safe save", by writing
+         to a new file and, if the write succeeds, renaming the
+         new file on top of the old file. */
+      if (file_exists(fname)) {
+        fname_new = g_strdup_printf("%s~", fname);
+        if (!copy_file_binary_mode(cf->filename, fname_new))
+          goto fail;
+      } else {
+        if (!copy_file_binary_mode(cf->filename, fname))
+          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. */
+    /* Either we're saving in a different format or we're saving changes,
+       such as added, modified, or removed comments, that haven't yet
+       been written to the underlying file; we can't do that by copying
+       or moving the capture file, we have to do it by writing the packets
+       out in Wiretap. */
 
     wtapng_section_t *shb_hdr = NULL;
     wtapng_iface_descriptions_t *idb_inf = NULL;
+    int encap;
 
     shb_hdr = wtap_file_get_shb_info(cf->wth);
     idb_inf = wtap_file_get_idb_info(cf->wth);
 
-    pdh = wtap_dump_open_ng(fname, save_format, cf->lnk_t, cf->snap,
-        compressed, shb_hdr, idb_inf, &err);
+    /* Determine what file encapsulation type we should use. */
+    encap = wtap_dump_file_encap_type(cf->linktypes);
+
+    if (file_exists(fname)) {
+      /* We're overwriting an existing file; write out to a new file,
+         and, if that succeeds, rename the new file on top of the
+         old file.  That makes this a "safe save", so that we don't
+         lose the old file if we have a problem writing out the new
+         file.  (If the existing file is the current capture file,
+         we *HAVE* to do that, otherwise we're overwriting the file
+         from which we're reading the packets that we're writing!) */
+      fname_new = g_strdup_printf("%s~", fname);
+      pdh = wtap_dump_open_ng(fname_new, save_format, encap, cf->snap,
+                              compressed, shb_hdr, idb_inf, &err);
+    } else {
+      pdh = wtap_dump_open_ng(fname, save_format, encap, cf->snap,
+                              compressed, shb_hdr, idb_inf, &err);
+    }
     g_free(idb_inf);
     idb_inf = NULL;
 
@@ -3900,23 +4370,11 @@ cf_save(capture_file *cf, const char *fname, packet_range_t *range, guint save_f
     /* Add address resolution */
     wtap_dump_set_addrinfo_list(pdh, get_addrinfo_list());
 
-    /* XXX - we let the user save a subset of the packets.
-
-       If we do that, should we make that file the current file?  If so,
-       it means we can no longer get at the other packets.  What does
-       NetMon do? */
-
-    /* Iterate through the list of packets, processing the packets we were
-       told to process.
-
-       XXX - we've already called "packet_range_process_init(range)", but
-       "process_specified_packets()" will do it again.  Fortunately,
-       that's harmless in this case, as we haven't done anything to
-       "range" since we initialized it. */
+    /* Iterate through the list of packets, processing all the packets. */
     callback_args.pdh = pdh;
     callback_args.fname = fname;
     callback_args.file_type = save_format;
-    switch (process_specified_packets(cf, range, "Saving", "selected packets",
+    switch (process_specified_packets(cf, NULL, "Saving", "packets",
                                       TRUE, save_packet, &callback_args)) {
 
     case PSP_FINISHED:
@@ -3925,11 +4383,20 @@ cf_save(capture_file *cf, const char *fname, packet_range_t *range, guint save_f
 
     case PSP_STOPPED:
       /* The user decided to abort the saving.
-         XXX - remove the output file? */
-      break;
+         If we're writing to a temporary file, remove it.
+         XXX - should we do so even if we're not writing to a
+         temporary file? */
+      wtap_dump_close(pdh, &err);
+      if (fname_new != NULL)
+        ws_unlink(fname_new);
+      cf_callback_invoke(cf_cb_file_save_stopped, NULL);
+      return CF_WRITE_ABORTED;
 
     case PSP_FAILED:
-      /* Error while saving. */
+      /* Error while saving.
+         If we're writing to a temporary file, remove it. */
+      if (fname_new != NULL)
+        ws_unlink(fname_new);
       wtap_dump_close(pdh, &err);
       goto fail;
     }
@@ -3938,213 +4405,435 @@ cf_save(capture_file *cf, const char *fname, packet_range_t *range, guint save_f
       cf_close_failure_alert_box(fname, err);
       goto fail;
     }
+
+    how_to_save = SAVE_WITH_WTAP;
+  }
+
+  if (fname_new != NULL) {
+    /* We wrote out to fname_new, and should rename it on top of
+       fname.  fname_new is now closed, so that should be possible even
+       on Windows.  However, on Windows, we first need to close whatever
+       file descriptors we have open for fname. */
+#ifdef _WIN32
+    wtap_fdclose(cf->wth);
+#endif
+    /* Now do the rename. */
+    if (ws_rename(fname_new, fname) == -1) {
+      /* Well, the rename failed. */
+      cf_rename_failure_alert_box(fname, errno);
+#ifdef _WIN32
+      /* Attempt to reopen the random file descriptor using the
+         current file's filename.  (At this point, the sequential
+         file descriptor is closed.) */
+      if (!wtap_fdreopen(cf->wth, cf->filename, &err)) {
+        /* Oh, well, we're screwed. */
+        display_basename = g_filename_display_basename(cf->filename);
+        simple_error_message_box(
+                      file_open_error_message(err, FALSE), display_basename);
+        g_free(display_basename);
+      }
+#endif
+      goto fail;
+    }
   }
 
   cf_callback_invoke(cf_cb_file_save_finished, NULL);
+  cf->unsaved_changes = FALSE;
 
-  if (packet_range_process_all(range)) {
-    /* We saved the entire capture, not just some packets from it.
-       Open and read the file we saved it to.
-
-       XXX - this is somewhat of a waste; we already have the
-       packets, all this gets us is updated file type information
-       (which we could just stuff into "cf"), and having the new
-       file be the one we have opened and from which we're reading
-       the data, and it means we have to spend time opening and
-       reading the file, which could be a significant amount of
-       time if the file is large. */
-    cf->unsaved_changes = FALSE;
-
-    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, 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;
+  if (!dont_reopen) {
+    switch (how_to_save) {
+
+    case SAVE_WITH_MOVE:
+      /* We just moved the file, so the wtap structure refers to the
+         new file, and all the information other than the filename
+         and the "is temporary" status applies to the new file; just
+         update that. */
+      g_free(cf->filename);
+      cf->filename = g_strdup(fname);
+      cf->is_tempfile = FALSE;
+      cf_callback_invoke(cf_cb_file_fast_save_finished, cf);
+      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;
+    case SAVE_WITH_COPY:
+      /* We just copied the file, s all the information other than
+         the wtap structure, the filename, and the "is temporary"
+         status applies to the new file; just update that. */
+      wtap_close(cf->wth);
+      cf->wth = wtap_open_offline(fname, &err, &err_info, TRUE);
+      if (cf->wth == NULL) {
+        cf_open_failure_alert_box(fname, err, err_info, FALSE, 0);
+        cf_close(cf);
+      } else {
+        g_free(cf->filename);
+        cf->filename = g_strdup(fname);
+        cf->is_tempfile = FALSE;
+      }
+      cf_callback_invoke(cf_cb_file_fast_save_finished, cf);
+      break;
+
+    case SAVE_WITH_WTAP:
+      /* Open and read the file we saved to.
+
+         XXX - this is somewhat of a waste; we already have the
+         packets, all this gets us is updated file type information
+         (which we could just stuff into "cf"), and having the new
+         file be the one we have opened and from which we're reading
+         the data, and it means we have to spend time opening and
+         reading the file, which could be a significant amount of
+         time if the file is large.
+
+         If the capture-file-writing code were to return the
+         seek offset of each packet it writes, we could save that
+         in the frame_data structure for the frame, and just open
+         the file without reading it again...
+
+         ...as long as, for gzipped files, the process of writing
+         out the file *also* generates the information needed to
+         support fast random access to the compressed file. */
+      if (rescan_file(cf, fname, FALSE, &err) != CF_READ_OK) {
+        /* The rescan failed; just close the file.  Either
+           a dialog was popped up for the failure, so the
+           user knows what happened, or they stopped the
+           rescan, in which case they know what happened. */
+        cf_close(cf);
+      }
+      break;
+    }
+
+    /* If we were told to discard the comments, do so. */
+    if (discard_comments) {
+      /* Remove SHB comment, if any. */
+      wtap_write_shb_comment(cf->wth, NULL);
+
+      /* Remove packet comments. */
+      for (framenum = 1; framenum <= cf->count; framenum++) {
+        fdata = frame_data_sequence_find(cf->frames, framenum);
+        if (fdata->opt_comment) {
+          g_free(fdata->opt_comment);
+          fdata->opt_comment = NULL;
+          cf->packet_comment_count--;
+        }
       }
-      cf_callback_invoke(cf_cb_file_save_reload_finished, cf);
     }
   }
-  return CF_OK;
+  return CF_WRITE_OK;
 
 fail:
+  if (fname_new != NULL) {
+    /* We were trying to write to a temporary file; get rid of it if it
+       exists.  (We don't care whether this fails, as, if it fails,
+       there's not much we can do about it.  I guess if it failed for
+       a reason other than "it doesn't exist", we could report an
+       error, so the user knows there's a junk file that they might
+       want to clean up.) */
+    ws_unlink(fname_new);
+    g_free(fname_new);
+  }
   cf_callback_invoke(cf_cb_file_save_failed, NULL);
-  return CF_ERROR;
+  return CF_WRITE_ERROR;
+}
+
+cf_write_status_t
+cf_export_specified_packets(capture_file *cf, const char *fname,
+                            packet_range_t *range, guint save_format,
+                            gboolean compressed)
+{
+  gchar                       *fname_new = NULL;
+  int                          err;
+  wtap_dumper                 *pdh;
+  save_callback_args_t         callback_args;
+  wtapng_section_t            *shb_hdr;
+  wtapng_iface_descriptions_t *idb_inf;
+  int                          encap;
+
+  cf_callback_invoke(cf_cb_file_export_specified_packets_started, (gpointer)fname);
+
+  packet_range_process_init(range);
+
+  /* We're writing out specified packets from the specified capture
+     file to another file.  Even if all captured packets are to be
+     written, don't special-case the operation - read each packet
+     and then write it out if it's one of the specified ones. */
+
+  shb_hdr = wtap_file_get_shb_info(cf->wth);
+  idb_inf = wtap_file_get_idb_info(cf->wth);
+
+  /* Determine what file encapsulation type we should use. */
+  encap = wtap_dump_file_encap_type(cf->linktypes);
+
+  if (file_exists(fname)) {
+    /* We're overwriting an existing file; write out to a new file,
+       and, if that succeeds, rename the new file on top of the
+       old file.  That makes this a "safe save", so that we don't
+       lose the old file if we have a problem writing out the new
+       file.  (If the existing file is the current capture file,
+       we *HAVE* to do that, otherwise we're overwriting the file
+       from which we're reading the packets that we're writing!) */
+    fname_new = g_strdup_printf("%s~", fname);
+    pdh = wtap_dump_open_ng(fname_new, save_format, encap, cf->snap,
+                            compressed, shb_hdr, idb_inf, &err);
+  } else {
+    pdh = wtap_dump_open_ng(fname, save_format, encap, cf->snap,
+                            compressed, shb_hdr, idb_inf, &err);
+  }
+  g_free(idb_inf);
+  idb_inf = NULL;
+
+  if (pdh == NULL) {
+    cf_open_failure_alert_box(fname, err, NULL, TRUE, save_format);
+    goto fail;
+  }
+
+  /* Add address resolution */
+  wtap_dump_set_addrinfo_list(pdh, get_addrinfo_list());
+
+  /* Iterate through the list of packets, processing the packets we were
+     told to process.
+
+     XXX - we've already called "packet_range_process_init(range)", but
+     "process_specified_packets()" will do it again.  Fortunately,
+     that's harmless in this case, as we haven't done anything to
+     "range" since we initialized it. */
+  callback_args.pdh = pdh;
+  callback_args.fname = fname;
+  callback_args.file_type = save_format;
+  switch (process_specified_packets(cf, range, "Writing", "specified packets",
+                                    TRUE, save_packet, &callback_args)) {
+
+  case PSP_FINISHED:
+    /* Completed successfully. */
+    break;
+
+  case PSP_STOPPED:
+      /* The user decided to abort the saving.
+         If we're writing to a temporary file, remove it.
+         XXX - should we do so even if we're not writing to a
+         temporary file? */
+      wtap_dump_close(pdh, &err);
+      if (fname_new != NULL)
+        ws_unlink(fname_new);
+      cf_callback_invoke(cf_cb_file_export_specified_packets_stopped, NULL);
+      return CF_WRITE_ABORTED;
+    break;
+
+  case PSP_FAILED:
+    /* Error while saving.
+       If we're writing to a temporary file, remove it. */
+    if (fname_new != NULL)
+      ws_unlink(fname_new);
+    wtap_dump_close(pdh, &err);
+    goto fail;
+  }
+
+  if (!wtap_dump_close(pdh, &err)) {
+    cf_close_failure_alert_box(fname, err);
+    goto fail;
+  }
+
+  if (fname_new != NULL) {
+    /* We wrote out to fname_new, and should rename it on top of
+       fname; fname is now closed, so that should be possible even
+       on Windows.  Do the rename. */
+    if (ws_rename(fname_new, fname) == -1) {
+      /* Well, the rename failed. */
+      cf_rename_failure_alert_box(fname, errno);
+      goto fail;
+    }
+  }
+
+  cf_callback_invoke(cf_cb_file_export_specified_packets_finished, NULL);
+  return CF_WRITE_OK;
+
+fail:
+  if (fname_new != NULL) {
+    /* We were trying to write to a temporary file; get rid of it if it
+       exists.  (We don't care whether this fails, as, if it fails,
+       there's not much we can do about it.  I guess if it failed for
+       a reason other than "it doesn't exist", we could report an
+       error, so the user knows there's a junk file that they might
+       want to clean up.) */
+    ws_unlink(fname_new);
+    g_free(fname_new);
+  }
+  cf_callback_invoke(cf_cb_file_export_specified_packets_failed, NULL);
+  return CF_WRITE_ERROR;
 }
 
 static void
 cf_open_failure_alert_box(const char *filename, int err, gchar *err_info,
                           gboolean for_writing, int file_type)
 {
+  gchar *display_basename;
+
   if (err < 0) {
     /* Wiretap error. */
+    display_basename = g_filename_display_basename(filename);
     switch (err) {
 
     case WTAP_ERR_NOT_REGULAR_FILE:
-      simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
+      simple_error_message_box(
             "The file \"%s\" is a \"special file\" or socket or other non-regular file.",
-            filename);
+            display_basename);
       break;
 
     case WTAP_ERR_RANDOM_OPEN_PIPE:
       /* Seen only when opening a capture file for reading. */
-      simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
+      simple_error_message_box(
             "The file \"%s\" is a pipe or FIFO; Wireshark can't read pipe or FIFO files.\n"
             "To capture from a pipe or FIFO use wireshark -i -",
-            filename);
+            display_basename);
       break;
 
     case WTAP_ERR_FILE_UNKNOWN_FORMAT:
       /* Seen only when opening a capture file for reading. */
-      simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
+      simple_error_message_box(
             "The file \"%s\" isn't a capture file in a format Wireshark understands.",
-            filename);
+            display_basename);
       break;
 
     case WTAP_ERR_UNSUPPORTED:
       /* Seen only when opening a capture file for reading. */
-      simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
+      simple_error_message_box(
             "The file \"%s\" isn't a capture file in a format Wireshark understands.\n"
             "(%s)",
-            filename, err_info);
+            display_basename, 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,
+      simple_error_message_box(
             "The file \"%s\" is a pipe, and %s capture files can't be "
             "written to a pipe.",
-            filename, wtap_file_type_string(file_type));
+            display_basename, 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,
+      simple_error_message_box(
             "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_error_message_box("Wireshark can't save this capture in that format.");
       } else {
-        simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
+        simple_error_message_box(
               "The file \"%s\" is a capture for a network type that Wireshark doesn't support.\n"
               "(%s)",
-              filename, err_info);
+              display_basename, 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,
+        simple_error_message_box(
               "Wireshark can't save this capture in that format.");
       } else {
-        simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
+        simple_error_message_box(
               "The file \"%s\" is a capture for a network type that Wireshark doesn't support.",
-              filename);
+              display_basename);
       }
       break;
 
     case WTAP_ERR_BAD_FILE:
       /* Seen only when opening a capture file for reading. */
-      simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
+      simple_error_message_box(
             "The file \"%s\" appears to be damaged or corrupt.\n"
             "(%s)",
-            filename, err_info);
+            display_basename, err_info);
       g_free(err_info);
       break;
 
     case WTAP_ERR_CANT_OPEN:
       if (for_writing) {
-        simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
+        simple_error_message_box(
               "The file \"%s\" could not be created for some unknown reason.",
-              filename);
+              display_basename);
       } else {
-        simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
+        simple_error_message_box(
               "The file \"%s\" could not be opened for some unknown reason.",
-              filename);
+              display_basename);
       }
       break;
 
     case WTAP_ERR_SHORT_READ:
-      simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
+      simple_error_message_box(
             "The file \"%s\" appears to have been cut short"
             " in the middle of a packet or other data.",
-            filename);
+            display_basename);
       break;
 
     case WTAP_ERR_SHORT_WRITE:
-      simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
+      simple_error_message_box(
             "A full header couldn't be written to the file \"%s\".",
-            filename);
+            display_basename);
       break;
 
     case WTAP_ERR_COMPRESSION_NOT_SUPPORTED:
-      simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
+      simple_error_message_box(
             "This file type cannot be written as a compressed file.");
       break;
 
     case WTAP_ERR_DECOMPRESS:
-      simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
+      simple_error_message_box(
             "The compressed file \"%s\" appears to be damaged or corrupt.\n"
-            "(%s)", filename, err_info);
+            "(%s)", display_basename, err_info);
       g_free(err_info);
       break;
 
     default:
-      simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
+      simple_error_message_box(
             "The file \"%s\" could not be %s: %s.",
-            filename,
+            display_basename,
             for_writing ? "created" : "opened",
             wtap_strerror(err));
       break;
     }
+    g_free(display_basename);
   } else {
     /* OS error. */
     open_failure_alert_box(filename, err, for_writing);
   }
 }
 
-static const char *
-file_rename_error_message(int err)
+/*
+ * XXX - whether we mention the source pathname, the target pathname,
+ * or both depends on the error and on what we find if we look for
+ * one or both of them.
+ */
+static void
+cf_rename_failure_alert_box(const char *filename, int err)
 {
-  const char *errmsg;
-  static char errmsg_errno[1024+1];
+  gchar *display_basename;
 
+  display_basename = g_filename_display_basename(filename);
   switch (err) {
 
   case ENOENT:
-    errmsg = "The path to the file \"%s\" doesn't exist.";
+    /* XXX - should check whether the source exists and, if not,
+       report it as the problem and, if so, report the destination
+       as the problem. */
+    simple_error_message_box("The path to the file \"%s\" doesn't exist.",
+                             display_basename);
     break;
 
   case EACCES:
-    errmsg = "You don't have permission to move the capture file to \"%s\".";
+    /* XXX - if we're doing a rename after a safe save, we should
+       probably say something else. */
+    simple_error_message_box("You don't have permission to move the capture file to \"%s\".",
+                             display_basename);
     break;
 
   default:
-    g_snprintf(errmsg_errno, sizeof(errmsg_errno),
-            "The file \"%%s\" could not be moved: %s.",
-                wtap_strerror(err));
-    errmsg = errmsg_errno;
+    /* XXX - this should probably mention both the source and destination
+       pathnames. */
+    simple_error_message_box("The file \"%s\" could not be moved: %s.",
+                             display_basename, wtap_strerror(err));
     break;
   }
-  return errmsg;
+  g_free(display_basename);
 }
 
 /* Check for write errors - if the file is being written to an NFS server,
@@ -4154,28 +4843,32 @@ file_rename_error_message(int err)
 static void
 cf_close_failure_alert_box(const char *filename, int err)
 {
+  gchar *display_basename;
+
   if (err < 0) {
     /* Wiretap error. */
+    display_basename = g_filename_display_basename(filename);
     switch (err) {
 
     case WTAP_ERR_CANT_CLOSE:
-      simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
+      simple_error_message_box(
             "The file \"%s\" couldn't be closed for some unknown reason.",
-            filename);
+            display_basename);
       break;
 
     case WTAP_ERR_SHORT_WRITE:
-      simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
+      simple_error_message_box(
             "Not all the packets could be written to the file \"%s\".",
-                    filename);
+                    display_basename);
       break;
 
     default:
-      simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
+      simple_error_message_box(
             "An error occurred while closing the file \"%s\": %s.",
-            filename, wtap_strerror(err));
+            display_basename, wtap_strerror(err));
       break;
     }
+    g_free(display_basename);
   } else {
     /* OS error.
        We assume that a close error from the OS is really a write error. */
@@ -4186,9 +4879,9 @@ cf_close_failure_alert_box(const char *filename, int err)
 /* Reload the current capture file. */
 void
 cf_reload(capture_file *cf) {
-  gchar *filename;
-  gboolean is_tempfile;
-  int err;
+  gchar    *filename;
+  gboolean  is_tempfile;
+  int       err;
 
   /* If the file could be opened, "cf_open()" calls "cf_close()"
      to get rid of state for the old capture file before filling in state
@@ -4204,7 +4897,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, FALSE)) {
+    switch (cf_read(cf, TRUE)) {
 
     case CF_READ_OK:
     case CF_READ_ERROR: