Prepare the docbooks for the 1.4 branch.
[metze/wireshark/wip.git] / file.c
diff --git a/file.c b/file.c
index a71629c2073f3a45407fe856c5579deae56ee97d..2c6c3eb5469f7da70ca57a3bfe92257e94f92a83 100644 (file)
--- a/file.c
+++ b/file.c
@@ -122,7 +122,7 @@ static void ref_time_packets(capture_file *cf);
 #endif
 /* Update the progress bar this many times when reading a file. */
 #define N_PROGBAR_UPDATES   100
-/* We read around 200k/100ms domt update the progress bar more often than that */
+/* We read around 200k/100ms don't update the progress bar more often than that */
 #define MIN_QUANTUM         200000
 #define MIN_NUMBER_OF_PACKET 1500
 
@@ -133,8 +133,8 @@ static void ref_time_packets(capture_file *cf);
 
 /* this callback mechanism should possibly be replaced by the g_signal_...() stuff (if I only would know how :-) */
 typedef struct {
-    cf_callback_t cb_fct;
-    gpointer user_data;
+  cf_callback_t cb_fct;
+  gpointer user_data;
 } cf_callback_data_t;
 
 static GList *cf_callbacks = NULL;
@@ -142,97 +142,97 @@ static GList *cf_callbacks = NULL;
 static void
 cf_callback_invoke(int event, gpointer data)
 {
-    cf_callback_data_t *cb;
-    GList *cb_item = cf_callbacks;
+  cf_callback_data_t *cb;
+  GList *cb_item = cf_callbacks;
 
-    /* there should be at least one interested */
-    g_assert(cb_item != NULL);
+  /* there should be at least one interested */
+  g_assert(cb_item != NULL);
 
-    while(cb_item != NULL) {
-        cb = cb_item->data;
-        cb->cb_fct(event, data, cb->user_data);
-        cb_item = g_list_next(cb_item);
-    }
+  while(cb_item != NULL) {
+    cb = cb_item->data;
+    cb->cb_fct(event, data, cb->user_data);
+    cb_item = g_list_next(cb_item);
+  }
 }
 
 
 void
 cf_callback_add(cf_callback_t func, gpointer user_data)
 {
-    cf_callback_data_t *cb;
+  cf_callback_data_t *cb;
 
-    cb = g_malloc(sizeof(cf_callback_data_t));
-    cb->cb_fct = func;
-    cb->user_data = user_data;
+  cb = g_malloc(sizeof(cf_callback_data_t));
+  cb->cb_fct = func;
+  cb->user_data = user_data;
 
-    cf_callbacks = g_list_append(cf_callbacks, cb);
+  cf_callbacks = g_list_append(cf_callbacks, cb);
 }
 
 void
 cf_callback_remove(cf_callback_t func)
 {
-    cf_callback_data_t *cb;
-    GList *cb_item = cf_callbacks;
-
-    while(cb_item != NULL) {
-        cb = cb_item->data;
-        if(cb->cb_fct == func) {
-            cf_callbacks = g_list_remove(cf_callbacks, cb);
-            g_free(cb);
-            return;
-        }
-        cb_item = g_list_next(cb_item);
+  cf_callback_data_t *cb;
+  GList *cb_item = cf_callbacks;
+
+  while(cb_item != NULL) {
+    cb = cb_item->data;
+    if(cb->cb_fct == func) {
+      cf_callbacks = g_list_remove(cf_callbacks, cb);
+      g_free(cb);
+      return;
     }
+    cb_item = g_list_next(cb_item);
+  }
 
-    g_assert_not_reached();
+  g_assert_not_reached();
 }
 
 void
 cf_timestamp_auto_precision(capture_file *cf)
 {
 #ifdef NEW_PACKET_LIST
-    int i;
+  int i;
 #endif
-    int prec = timestamp_get_precision();
+  int prec = timestamp_get_precision();
 
 
-    /* don't try to get the file's precision if none is opened */
-    if(cf->state == FILE_CLOSED) {
-        return;
-    }
+  /* don't try to get the file's precision if none is opened */
+  if(cf->state == FILE_CLOSED) {
+    return;
+  }
 
-    /* if we are in auto mode, set precision of current file */
-    if(prec == TS_PREC_AUTO ||
-      prec == TS_PREC_AUTO_SEC ||
-      prec == TS_PREC_AUTO_DSEC ||
-      prec == TS_PREC_AUTO_CSEC ||
-      prec == TS_PREC_AUTO_MSEC ||
-      prec == TS_PREC_AUTO_USEC ||
-      prec == TS_PREC_AUTO_NSEC)
-    {
-        switch(wtap_file_tsprecision(cf->wth)) {
-        case(WTAP_FILE_TSPREC_SEC):
-            timestamp_set_precision(TS_PREC_AUTO_SEC);
-            break;
-        case(WTAP_FILE_TSPREC_DSEC):
-            timestamp_set_precision(TS_PREC_AUTO_DSEC);
-            break;
-        case(WTAP_FILE_TSPREC_CSEC):
-            timestamp_set_precision(TS_PREC_AUTO_CSEC);
-            break;
-        case(WTAP_FILE_TSPREC_MSEC):
-            timestamp_set_precision(TS_PREC_AUTO_MSEC);
-            break;
-        case(WTAP_FILE_TSPREC_USEC):
-            timestamp_set_precision(TS_PREC_AUTO_USEC);
-            break;
-        case(WTAP_FILE_TSPREC_NSEC):
-            timestamp_set_precision(TS_PREC_AUTO_NSEC);
-            break;
-        default:
-            g_assert_not_reached();
-        }
+  /* if we are in auto mode, set precision of current file */
+  if(prec == TS_PREC_AUTO ||
+     prec == TS_PREC_AUTO_SEC ||
+     prec == TS_PREC_AUTO_DSEC ||
+     prec == TS_PREC_AUTO_CSEC ||
+     prec == TS_PREC_AUTO_MSEC ||
+     prec == TS_PREC_AUTO_USEC ||
+     prec == TS_PREC_AUTO_NSEC)
+  {
+    switch(wtap_file_tsprecision(cf->wth)) {
+    case(WTAP_FILE_TSPREC_SEC):
+      timestamp_set_precision(TS_PREC_AUTO_SEC);
+      break;
+    case(WTAP_FILE_TSPREC_DSEC):
+      timestamp_set_precision(TS_PREC_AUTO_DSEC);
+      break;
+    case(WTAP_FILE_TSPREC_CSEC):
+      timestamp_set_precision(TS_PREC_AUTO_CSEC);
+      break;
+    case(WTAP_FILE_TSPREC_MSEC):
+      timestamp_set_precision(TS_PREC_AUTO_MSEC);
+      break;
+    case(WTAP_FILE_TSPREC_USEC):
+      timestamp_set_precision(TS_PREC_AUTO_USEC);
+      break;
+    case(WTAP_FILE_TSPREC_NSEC):
+      timestamp_set_precision(TS_PREC_AUTO_NSEC);
+      break;
+    default:
+      g_assert_not_reached();
     }
+  }
 #ifdef NEW_PACKET_LIST
   /* Set the column widths of those columns that show the time in
      "command-line-specified" format. */
@@ -247,25 +247,25 @@ cf_timestamp_auto_precision(capture_file *cf)
 gulong
 cf_get_computed_elapsed(void)
 {
-    return computed_elapsed;
+  return computed_elapsed;
 }
 
 static void reset_elapsed(void)
 {
-    computed_elapsed = 0;
+  computed_elapsed = 0;
 }
 
 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);
+  g_get_current_time(&time_now);
 
-    delta_time = (time_now.tv_sec - start_time->tv_sec) * 1e6 +
+  delta_time = (time_now.tv_sec - start_time->tv_sec) * 1e6 +
     time_now.tv_usec - start_time->tv_usec;
 
-    computed_elapsed = (gulong) (delta_time / 1000); /* ms*/
+  computed_elapsed = (gulong) (delta_time / 1000); /* ms*/
 }
 
 cf_status_t
@@ -310,6 +310,7 @@ cf_open(capture_file *cf, const char *fname, gboolean is_tempfile, int *err)
   cf->count     = 0;
   cf->displayed_count = 0;
   cf->marked_count = 0;
+  cf->ignored_count = 0;
   cf->drops_known = FALSE;
   cf->drops     = 0;
   cf->snap      = wtap_snapshot_length(cf->wth);
@@ -464,27 +465,27 @@ static void outofmemory_cb(gpointer dialog _U_, gint btn _U_, gpointer data _U_)
 
 static float calc_progbar_val(capture_file *cf, gint64 size, gint64 file_pos){
 
-    float   progbar_val;
+  float   progbar_val;
 
-    progbar_val = (gfloat) file_pos / (gfloat) size;
-    if (progbar_val > 1.0) {
+  progbar_val = (gfloat) file_pos / (gfloat) size;
+  if (progbar_val > 1.0) {
     /* The file probably grew while we were reading it.
        Update file size, and try again. */
-      size = wtap_file_size(cf->wth, NULL);
-      if (size >= 0)
-        progbar_val = (gfloat) file_pos / (gfloat) size;
-       /* If it's still > 1, either "wtap_file_size()" failed (in which
-          case there's not much we can do about it), or the file
-          *shrank* (in which case there's not much we can do about
-          it); just clip the progress value at 1.0. */
-      if (progbar_val > 1.0f)
-        progbar_val = 1.0f;
-    }
-    return progbar_val;
+    size = wtap_file_size(cf->wth, NULL);
+    if (size >= 0)
+      progbar_val = (gfloat) file_pos / (gfloat) size;
+    /* If it's still > 1, either "wtap_file_size()" failed (in which
+       case there's not much we can do about it), or the file
+       *shrank* (in which case there's not much we can do about
+       it); just clip the progress value at 1.0. */
+    if (progbar_val > 1.0f)
+      progbar_val = 1.0f;
+  }
+  return progbar_val;
 }
 
 cf_read_status_t
-cf_read(capture_file *cf)
+cf_read(capture_file *cf, gboolean from_save)
 {
   int         err;
   gchar       *err_info;
@@ -524,10 +525,13 @@ cf_read(capture_file *cf)
 
   reset_tap_listeners();
 
-  cf_callback_invoke(cf_cb_file_read_start, cf);
-
   name_ptr = get_basename(cf->filename);
 
+  if (from_save == FALSE)
+    cf_callback_invoke(cf_cb_file_read_started, cf);
+  else
+    cf_callback_invoke(cf_cb_file_save_started, (gpointer)name_ptr);
+
   /* Find the size of the file. */
   size = wtap_file_size(cf->wth, NULL);
 
@@ -538,7 +542,7 @@ cf_read(capture_file *cf)
   if (size >= 0){
     progbar_quantum = size/N_PROGBAR_UPDATES;
     if (progbar_quantum < MIN_QUANTUM)
-        progbar_quantum = MIN_QUANTUM;
+      progbar_quantum = MIN_QUANTUM;
   }else
     progbar_quantum = 0;
   /* Progress so far. */
@@ -555,14 +559,18 @@ cf_read(capture_file *cf)
 
   while ((wtap_read(cf->wth, &err, &err_info, &data_offset))) {
     if (size >= 0) {
-        count++;
+      count++;
       /* Create the progress bar if necessary.
        * Check wether it should be created or not every MIN_NUMBER_OF_PACKET
        */
       if ((progbar == NULL) && !(count % MIN_NUMBER_OF_PACKET)){
         progbar_val = calc_progbar_val( cf, size, data_offset);
-        progbar = delayed_create_progress_dlg("Loading", name_ptr,
-          TRUE, &stop_flag, &start_time, progbar_val);
+        if (from_save == FALSE)
+          progbar = delayed_create_progress_dlg("Loading", name_ptr,
+                                                TRUE, &stop_flag, &start_time, progbar_val);
+        else
+          progbar = delayed_create_progress_dlg("Saving", name_ptr,
+                                                TRUE, &stop_flag, &start_time, progbar_val);
       }
 
       /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
@@ -571,34 +579,34 @@ cf_read(capture_file *cf)
          to see if there's any pending input from an X server, and doing
          that for every packet can be costly, especially on a big file. */
       if (data_offset >= progbar_nextstep) {
-          if (progbar != NULL) {
-              progbar_val = calc_progbar_val( cf, size, data_offset);
-              /* update the packet lists content on the first run or frequently on very large files */
-              /* (on smaller files the display update takes longer than reading the file) */
+        if (progbar != NULL) {
+          progbar_val = calc_progbar_val( cf, size, data_offset);
+          /* update the packet lists content on the first run or frequently on very large files */
+          /* (on smaller files the display update takes longer than reading the file) */
 #ifdef HAVE_LIBPCAP
-              if (progbar_quantum > 500000 || displayed_once == 0) {
-                  if ((auto_scroll_live || displayed_once == 0 || cf->displayed_count < 1000) && cf->plist_end != NULL) {
-                      displayed_once = 1;
+          if (progbar_quantum > 500000 || displayed_once == 0) {
+            if ((auto_scroll_live || displayed_once == 0 || cf->displayed_count < 1000) && cf->plist_end != NULL) {
+              displayed_once = 1;
 #ifdef NEW_PACKET_LIST
-                  new_packet_list_thaw();
-                  if (auto_scroll_live)
-                      new_packet_list_moveto_end();
-                  new_packet_list_freeze();
+              new_packet_list_thaw();
+              if (auto_scroll_live)
+                new_packet_list_moveto_end();
+              new_packet_list_freeze();
 #else
-                  packet_list_thaw();
-                  if (auto_scroll_live)
-                      packet_list_moveto_end();
-                  packet_list_freeze();
+              packet_list_thaw();
+              if (auto_scroll_live)
+                packet_list_moveto_end();
+              packet_list_freeze();
 #endif /* NEW_PACKET_LIST */
-                  }
+            }
           }
 #endif /* HAVE_LIBPCAP */
-            g_snprintf(status_str, sizeof(status_str),
-                       "%" G_GINT64_MODIFIER "dKB of %" G_GINT64_MODIFIER "dKB",
-                       data_offset / 1024, size / 1024);
-            update_progress_dlg(progbar, progbar_val, status_str);
-          }
-         progbar_nextstep += progbar_quantum;
+          g_snprintf(status_str, sizeof(status_str),
+                     "%" G_GINT64_MODIFIER "dKB of %" G_GINT64_MODIFIER "dKB",
+                     data_offset / 1024, size / 1024);
+          update_progress_dlg(progbar, progbar_val, status_str);
+        }
+        progbar_nextstep += progbar_quantum;
       }
     }
 
@@ -612,27 +620,27 @@ cf_read(capture_file *cf)
       break;
     }
     TRY {
-        read_packet(cf, dfcode, filtering_tap_listeners, tap_flags, data_offset);
+      read_packet(cf, dfcode, filtering_tap_listeners, tap_flags, data_offset);
     }
     CATCH(OutOfMemoryError) {
-        gpointer dialog;
-
-        dialog = simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
-              "%sOut Of Memory!%s\n"
-              "\n"
-              "Sorry, but Wireshark has to terminate now!\n"
-              "\n"
-              "Some infos / workarounds can be found at:\n"
-              "http://wiki.wireshark.org/KnownBugs/OutOfMemory",
-              simple_dialog_primary_start(), simple_dialog_primary_end());
-        /* we have to terminate, as we cannot recover from the memory error */
-        simple_dialog_set_cb(dialog, outofmemory_cb, NULL);
-        while(1) {
-            main_window_update();
-            /* XXX - how to avoid a busy wait? */
-            /* Sleep(100); */
-        };
-        break;
+      gpointer dialog;
+
+      dialog = simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
+                             "%sOut Of Memory!%s\n"
+                             "\n"
+                             "Sorry, but Wireshark has to terminate now!\n"
+                             "\n"
+                             "Some infos / workarounds can be found at:\n"
+                             "http://wiki.wireshark.org/KnownBugs/OutOfMemory",
+                             simple_dialog_primary_start(), simple_dialog_primary_end());
+      /* we have to terminate, as we cannot recover from the memory error */
+      simple_dialog_set_cb(dialog, outofmemory_cb, NULL);
+      while(1) {
+        main_window_update();
+        /* XXX - how to avoid a busy wait? */
+        /* Sleep(100); */
+      };
+      break;
     }
     ENDTRY;
   }
@@ -673,8 +681,10 @@ cf_read(capture_file *cf)
 #else
   packet_list_thaw();
 #endif
-
-  cf_callback_invoke(cf_cb_file_read_finished, cf);
+  if (from_save == FALSE)
+    cf_callback_invoke(cf_cb_file_read_finished, cf);
+  else
+    cf_callback_invoke(cf_cb_file_save_finished, cf);
 
   /* If we have any displayed packets to select, select the first of those
      packets by making the first row the selected row. */
@@ -688,13 +698,13 @@ cf_read(capture_file *cf)
 
   if(stop_flag) {
     simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
-          "%sFile loading was cancelled!%s\n"
-          "\n"
-          "The remaining packets in the file were discarded.\n"
-          "\n"
-          "As a lot of packets from the original file will be missing,\n"
-          "remember to be careful when saving the current content to a file.\n",
-          simple_dialog_primary_start(), simple_dialog_primary_end());
+                  "%sFile loading was cancelled!%s\n"
+                  "\n"
+                  "The remaining packets in the file were discarded.\n"
+                  "\n"
+                  "As a lot of packets from the original file will be missing,\n"
+                  "remember to be careful when saving the current content to a file.\n",
+                  simple_dialog_primary_start(), simple_dialog_primary_end());
     return CF_READ_ERROR;
   }
 
@@ -706,34 +716,34 @@ cf_read(capture_file *cf)
 
     case WTAP_ERR_UNSUPPORTED_ENCAP:
       g_snprintf(errmsg_errno, sizeof(errmsg_errno),
-               "The capture file has a packet with a network type that Wireshark doesn't support.\n(%s)",
-               err_info);
+                 "The capture file has a packet with a network type that Wireshark doesn't support.\n(%s)",
+                 err_info);
       g_free(err_info);
       errmsg = errmsg_errno;
       break;
 
     case WTAP_ERR_CANT_READ:
       errmsg = "An attempt to read from the capture file failed for"
-               " some unknown reason.";
+        " some unknown reason.";
       break;
 
     case WTAP_ERR_SHORT_READ:
       errmsg = "The capture file appears to have been cut short"
-               " in the middle of a packet.";
+        " in the middle of a packet.";
       break;
 
     case WTAP_ERR_BAD_RECORD:
       g_snprintf(errmsg_errno, sizeof(errmsg_errno),
-               "The capture file appears to be damaged or corrupt.\n(%s)",
-               err_info);
+                 "The capture file appears to be damaged or corrupt.\n(%s)",
+                 err_info);
       g_free(err_info);
       errmsg = errmsg_errno;
       break;
 
     default:
       g_snprintf(errmsg_errno, sizeof(errmsg_errno),
-           "An error occurred while reading the"
-           " capture file: %s.", wtap_strerror(err));
+                 "An error occurred while reading the"
+                 " capture file: %s.", wtap_strerror(err));
       errmsg = errmsg_errno;
       break;
     }
@@ -782,7 +792,8 @@ cf_continue_tail(capture_file *cf, volatile int to_read, int *err)
 
 #ifdef NEW_PACKET_LIST
   new_packet_list_check_end();
-  new_packet_list_freeze();
+  /* Don't freeze/thaw the list when doing live capture */
+  /*new_packet_list_freeze();*/
 #else
   packet_list_check_end();
   packet_list_freeze();
@@ -790,49 +801,51 @@ cf_continue_tail(capture_file *cf, volatile int to_read, int *err)
 
   /*g_log(NULL, G_LOG_LEVEL_MESSAGE, "cf_continue_tail: %u new: %u", cf->count, to_read);*/
 
+  wtap_cleareof(cf->wth);
   while (to_read != 0 && (wtap_read(cf->wth, err, &err_info, &data_offset))) {
     if (cf->state == FILE_READ_ABORTED) {
       /* Well, the user decided to exit Wireshark.  Break out of the
          loop, and let the code below (which is called even if there
-     aren't any packets left to read) exit. */
+         aren't any packets left to read) exit. */
       break;
     }
     TRY{
-        if (read_packet(cf, dfcode, filtering_tap_listeners, tap_flags,
-                        data_offset) != -1) {
-            visible = TRUE;
-            newly_displayed_packets++;
-        }else{
-            visible = FALSE;
-        }
+      if (read_packet(cf, dfcode, filtering_tap_listeners, tap_flags,
+                      data_offset) != -1) {
+        visible = TRUE;
+        newly_displayed_packets++;
+      }else{
+        visible = FALSE;
+      }
     }
     CATCH(OutOfMemoryError) {
-        gpointer dialog;
-
-        dialog = simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
-              "%sOut Of Memory!%s\n"
-              "\n"
-              "Sorry, but Wireshark has to terminate now!\n"
-              "\n"
-              "The capture file is not lost, it can be found at:\n"
-              "%s\n"
-              "\n"
-              "Some infos / workarounds can be found at:\n"
-              "http://wiki.wireshark.org/KnownBugs/OutOfMemory",
-              simple_dialog_primary_start(), simple_dialog_primary_end(), cf->filename);
-        /* we have to terminate, as we cannot recover from the memory error */
-        simple_dialog_set_cb(dialog, outofmemory_cb, NULL);
-        while(1) {
-            main_window_update();
-            /* XXX - how to avoid a busy wait? */
-            /* Sleep(100); */
-        };
+      gpointer dialog;
+
+      dialog = simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
+                             "%sOut Of Memory!%s\n"
+                             "\n"
+                             "Sorry, but Wireshark has to terminate now!\n"
+                             "\n"
+                             "The capture file is not lost, it can be found at:\n"
+                             "%s\n"
+                             "\n"
+                             "Some infos / workarounds can be found at:\n"
+                             "http://wiki.wireshark.org/KnownBugs/OutOfMemory",
+                             simple_dialog_primary_start(), simple_dialog_primary_end(), cf->filename);
+      /* we have to terminate, as we cannot recover from the memory error */
+      simple_dialog_set_cb(dialog, outofmemory_cb, NULL);
+      while(1) {
+        main_window_update();
+        /* XXX - how to avoid a busy wait? */
+        /* Sleep(100); */
+      };
 #ifdef NEW_PACKET_LIST
-        new_packet_list_thaw();
+      /* Don't freeze/thaw the list when doing live capture */
+      /*new_packet_list_thaw();*/
 #else
-        packet_list_thaw();
+      packet_list_thaw();
 #endif
-        return CF_READ_ABORTED;
+      return CF_READ_ABORTED;
     }
     ENDTRY;
     to_read--;
@@ -844,15 +857,16 @@ cf_continue_tail(capture_file *cf, volatile int to_read, int *err)
   }
 
   /*g_log(NULL, G_LOG_LEVEL_MESSAGE, "cf_continue_tail: count %u state: %u err: %u",
-      cf->count, cf->state, *err);*/
+    cf->count, cf->state, *err);*/
 
 #ifdef NEW_PACKET_LIST
-  new_packet_list_thaw();
+  /* Don't freeze/thaw the list when doing live capture */
+  /*new_packet_list_thaw();*/
   /* With the new packet list the first packet
    * isn't automatically selected.
    */
   if(!cf->current_frame)
-         new_packet_list_select_first_row();
+    new_packet_list_select_first_row();
 #else
   /* XXX - this causes "flickering" of the list */
   packet_list_thaw();
@@ -920,7 +934,8 @@ cf_finish_tail(capture_file *cf, int *err)
 
 #ifdef NEW_PACKET_LIST
   new_packet_list_check_end();
-  new_packet_list_freeze();
+  /* Don't freeze/thaw the list when doing live capture */
+  /*new_packet_list_freeze();*/
 #else
   packet_list_check_end();
   packet_list_freeze();
@@ -942,7 +957,8 @@ cf_finish_tail(capture_file *cf, int *err)
   }
 
 #ifdef NEW_PACKET_LIST
-  new_packet_list_thaw();
+  /* Don't freeze/thaw the list when doing live capture */
+  /*new_packet_list_thaw();*/
 #else
   packet_list_thaw();
 #endif
@@ -1009,65 +1025,89 @@ cf_get_display_name(capture_file *cf)
   } else {
     /* The file we read is a temporary file from a live capture;
        we don't mention its name. */
-    displayname = "(Untitled)";
+    if (cf->source) {
+      displayname = cf->source;
+    } else {
+      displayname = "(Untitled)";
+    }
   }
   return displayname;
 }
 
+void cf_set_tempfile_source(capture_file *cf, gchar *source) {
+  if (cf->source) {
+    g_free(cf->source);
+  }
+
+  if (source) {
+    cf->source = g_strdup(source);
+  } else {
+    cf->source = g_strdup("");
+  }
+}
+
+const gchar *cf_get_tempfile_source(capture_file *cf) {
+  if (!cf->source) {
+    return "";
+  }
+
+  return cf->source;
+}
+
 /* XXX - use a macro instead? */
 int
 cf_get_packet_count(capture_file *cf)
 {
-    return cf->count;
+  return cf->count;
 }
 
 /* XXX - use a macro instead? */
 void
 cf_set_packet_count(capture_file *cf, int packet_count)
 {
-    cf->count = packet_count;
+  cf->count = packet_count;
 }
 
 /* XXX - use a macro instead? */
 gboolean
 cf_is_tempfile(capture_file *cf)
 {
-    return cf->is_tempfile;
+  return cf->is_tempfile;
 }
 
 void cf_set_tempfile(capture_file *cf, gboolean is_tempfile)
 {
-    cf->is_tempfile = is_tempfile;
+  cf->is_tempfile = is_tempfile;
 }
 
 
 /* XXX - use a macro instead? */
 void cf_set_drops_known(capture_file *cf, gboolean drops_known)
 {
-    cf->drops_known = drops_known;
+  cf->drops_known = drops_known;
 }
 
 /* XXX - use a macro instead? */
 void cf_set_drops(capture_file *cf, guint32 drops)
 {
-    cf->drops = drops;
+  cf->drops = drops;
 }
 
 /* XXX - use a macro instead? */
 gboolean cf_get_drops_known(capture_file *cf)
 {
-    return cf->drops_known;
+  return cf->drops_known;
 }
 
 /* XXX - use a macro instead? */
 guint32 cf_get_drops(capture_file *cf)
 {
-    return cf->drops;
+  return cf->drops;
 }
 
 void cf_set_rfcode(capture_file *cf, dfilter_t *rfcode)
 {
-    cf->rfcode = rfcode;
+  cf->rfcode = rfcode;
 }
 
 #ifdef NEW_PACKET_LIST
@@ -1264,6 +1304,9 @@ add_packet_to_packet_list(frame_data *fdata, capture_file *cf,
      if (fdata->flags.marked) {
        packet_list_set_colors(row, &prefs.gui_marked_fg, &prefs.gui_marked_bg);
      }
+     if (fdata->flags.ignored) {
+       packet_list_set_colors(row, &prefs.gui_ignored_fg, &prefs.gui_ignored_bg);
+     }
 
     cf->displayed_count++;
   }
@@ -1581,6 +1624,7 @@ cf_filter_packets(capture_file *cf, gchar *dftext, gboolean force)
   const char *filter_new = dftext ? dftext : "";
   const char *filter_old = cf->dfilter ? cf->dfilter : "";
   dfilter_t   *dfcode;
+  GTimeVal     start_time;
 
   /* if new filter equals old one, do nothing unless told to do so */
   if (!force && strcmp(filter_new, filter_old) == 0) {
@@ -1628,6 +1672,8 @@ cf_filter_packets(capture_file *cf, gchar *dftext, gboolean force)
   /* We have a valid filter.  Replace the current filter. */
   g_free(cf->dfilter);
   cf->dfilter = dftext;
+  g_get_current_time(&start_time);
+
 
   /* Now rescan the packet list, applying the new filter, but not
      throwing away information constructed on a previous pass. */
@@ -1759,8 +1805,6 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item,
   cf->first_displayed = NULL;
   cf->last_displayed = NULL;
 
-  reset_elapsed();
-
   /* We currently don't display any packets */
   cf->displayed_count = 0;
 
@@ -1930,6 +1974,9 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item,
   if (!add_to_packet_list)
     new_packet_list_recreate_visible_rows();
 
+  /* Compute the time it took to filter the file */
+  compute_elapsed(&start_time);
+
   new_packet_list_thaw();
 
   if (selected_frame_num == -1) {
@@ -1975,6 +2022,8 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item,
     /* Either the frame that was selected passed the filter, or we've
        found the nearest displayed frame to that frame.  Select it, make
        it the focus row, and make it visible. */
+    /* Set to invalid to force update of packet list and packet details */
+    cf->current_row = -1;
     if (selected_frame_num == 0) {
       new_packet_list_select_first_row();
     }else{
@@ -2586,6 +2635,7 @@ print_packet(capture_file *cf, frame_data *fdata,
   /* Fill in the column information if we're printing the summary
      information. */
   if (args->print_args->print_summary) {
+    col_custom_prime_edt(&edt, &cf->cinfo);
     epan_dissect_run(&edt, pseudo_header, pd, fdata, &cf->cinfo);
     epan_dissect_fill_in_columns(&edt, FALSE, TRUE);
   } else
@@ -2918,6 +2968,7 @@ write_psml_packet(capture_file *cf, frame_data *fdata,
      if having custom columns. */
   proto_tree_needed = have_custom_cols(&cf->cinfo);
   epan_dissect_init(&edt, proto_tree_needed, proto_tree_needed);
+  col_custom_prime_edt(&edt, &cf->cinfo);
   epan_dissect_run(&edt, pseudo_header, pd, fdata, &cf->cinfo);
   epan_dissect_fill_in_columns(&edt, FALSE, TRUE);
 
@@ -2992,6 +3043,7 @@ write_csv_packet(capture_file *cf, frame_data *fdata,
      if having custom columns. */
   proto_tree_needed = have_custom_cols(&cf->cinfo);
   epan_dissect_init(&edt, proto_tree_needed, proto_tree_needed);
+  col_custom_prime_edt(&edt, &cf->cinfo);
   epan_dissect_run(&edt, pseudo_header, pd, fdata, &cf->cinfo);
   epan_dissect_fill_in_columns(&edt, FALSE, TRUE);
 
@@ -3639,7 +3691,7 @@ find_packet(capture_file *cf,
   gchar       status_str[100];
   int         progbar_nextstep;
   int         progbar_quantum;
-  char       *title;
+  const char *title;
 
   start_fd = cf->current_frame;
   if (start_fd != NULL)  {
@@ -3716,18 +3768,12 @@ find_packet(capture_file *cf,
 
           if (prefs.gui_find_wrap)
           {
-              simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
-                            "%sBeginning of capture exceeded!%s\n\n"
-                            "Search is continued from the end of the capture.",
-                            simple_dialog_primary_start(), simple_dialog_primary_end());
+              simple_status("Search reached the beginning. Continuing at end.");
               fdata = cf->plist_end;    /* wrap around */
           }
           else
           {
-              simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
-                            "%sBeginning of capture exceeded!%s\n\n"
-                            "Try searching forwards.",
-                            simple_dialog_primary_start(), simple_dialog_primary_end());
+              simple_status("Search reached the beginning.");
               fdata = start_fd;        /* stay on previous packet */
           }
         }
@@ -3737,18 +3783,12 @@ find_packet(capture_file *cf,
         if (fdata == NULL) {
           if (prefs.gui_find_wrap)
           {
-              simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
-                            "%sEnd of capture exceeded!%s\n\n"
-                            "Search is continued from the start of the capture.",
-                            simple_dialog_primary_start(), simple_dialog_primary_end());
+              simple_status("Search reached the end. Continuing at beginning.");
               fdata = cf->plist_start;    /* wrap around */
           }
           else
           {
-              simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
-                            "%sEnd of capture exceeded!%s\n\n"
-                            "Try searching backwards.",
-                            simple_dialog_primary_start(), simple_dialog_primary_end());
+              simple_status("Search reached the end.");
               fdata = start_fd;     /* stay on previous packet */
           }
         }
@@ -3828,15 +3868,13 @@ cf_goto_frame(capture_file *cf, guint fnumber)
 
   if (fdata == NULL) {
     /* we didn't find a packet with that packet number */
-    simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
-          "There is no packet with the packet number %u.", fnumber);
+    simple_status("There is no packet number %u.", fnumber);
     return FALSE;   /* we failed to go to that packet */
   }
   if (!fdata->flags.passed_dfilter) {
     /* that packet currently isn't displayed */
     /* XXX - add it to the set of displayed packets? */
-    simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
-          "The packet number %u isn't currently being displayed.", fnumber);
+    simple_status("Packet number %u isn't displayed.", fnumber);
     return FALSE;   /* we failed to go to that packet */
   }
 
@@ -4075,6 +4113,32 @@ cf_unmark_frame(capture_file *cf, frame_data *frame)
   }
 }
 
+/*
+ * Ignore a particular frame.
+ */
+void
+cf_ignore_frame(capture_file *cf, frame_data *frame)
+{
+  if (! frame->flags.ignored) {
+    frame->flags.ignored = TRUE;
+    if (cf->count > cf->ignored_count)
+      cf->ignored_count++;
+  }
+}
+
+/*
+ * Un-ignore a particular frame.
+ */
+void
+cf_unignore_frame(capture_file *cf, frame_data *frame)
+{
+  if (frame->flags.ignored) {
+    frame->flags.ignored = FALSE;
+    if (cf->ignored_count > 0)
+      cf->ignored_count--;
+  }
+}
+
 typedef struct {
   wtap_dumper *pdh;
   const char  *fname;
@@ -4142,7 +4206,7 @@ cf_save(capture_file *cf, const char *fname, packet_range_t *range, guint save_f
   wtap_dumper  *pdh;
   save_callback_args_t callback_args;
 
-  cf_callback_invoke(cf_cb_file_safe_started, (gpointer) fname);
+  cf_callback_invoke(cf_cb_file_save_started, (gpointer)fname);
 
   /* don't write over an existing file. */
   /* this should've been already checked by our caller, just to be sure... */
@@ -4156,7 +4220,6 @@ cf_save(capture_file *cf, const char *fname, packet_range_t *range, guint save_f
 
   packet_range_process_init(range);
 
-
   if (packet_range_process_all(range) && save_format == cf->cd_t) {
     /* We're not filtering packets, and we're saving it in the format
        it's already in, so we can just move or copy the raw data. */
@@ -4255,7 +4318,7 @@ cf_save(capture_file *cf, const char *fname, packet_range_t *range, guint save_f
     }
   }
 
-  cf_callback_invoke(cf_cb_file_safe_finished, NULL);
+  cf_callback_invoke(cf_cb_file_save_finished, NULL);
 
   if (packet_range_process_all(range)) {
     /* We saved the entire capture, not just some packets from it.
@@ -4273,7 +4336,8 @@ cf_save(capture_file *cf, const char *fname, packet_range_t *range, guint save_f
     if ((cf_open(cf, fname, FALSE, &err)) == CF_OK) {
       /* XXX - report errors if this fails?
          What should we return if it fails or is aborted? */
-      switch (cf_read(cf)) {
+
+      switch (cf_read(cf, TRUE)) {
 
       case CF_READ_OK:
       case CF_READ_ERROR:
@@ -4289,13 +4353,13 @@ cf_save(capture_file *cf, const char *fname, packet_range_t *range, guint save_f
        correctly for the "no capture file open" state). */
     break;
       }
-      cf_callback_invoke(cf_cb_file_safe_reload_finished, NULL);
+      cf_callback_invoke(cf_cb_file_save_reload_finished, cf);
     }
   }
   return CF_OK;
 
 fail:
-  cf_callback_invoke(cf_cb_file_safe_failed, NULL);
+  cf_callback_invoke(cf_cb_file_save_failed, NULL);
   return CF_ERROR;
 }
 
@@ -4554,7 +4618,7 @@ cf_reload(capture_file *cf) {
   is_tempfile = cf->is_tempfile;
   cf->is_tempfile = FALSE;
   if (cf_open(cf, filename, is_tempfile, &err) == CF_OK) {
-    switch (cf_read(cf)) {
+    switch (cf_read(cf, FALSE)) {
 
     case CF_READ_OK:
     case CF_READ_ERROR:
@@ -4584,3 +4648,16 @@ cf_reload(capture_file *cf) {
      we should free up our copy. */
   g_free(filename);
 }
+
+/*
+ * Editor modelines
+ *
+ * Local Variables:
+ * c-basic-offset: 2
+ * tab-width: 8
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * ex: set shiftwidth=2 tabstop=8 expandtab
+ * :indentSize=2:tabSize=8:noTabs=true:
+ */