Add support for Banyan Vines addresses to the code that handles the
[obnox/wireshark/wip.git] / file.c
diff --git a/file.c b/file.c
index b34e86d702bed310f5022de70e679315401f45b2..d8e920c183eeee1648e01b4852cfde7c896304dd 100644 (file)
--- a/file.c
+++ b/file.c
@@ -1,7 +1,7 @@
 /* file.c
  * File I/O routines
  *
- * $Id: file.c,v 1.69 1999/08/15 00:55:22 guy Exp $
+ * $Id: file.c,v 1.112 1999/10/22 08:30:02 guy Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@zing.org>
@@ -35,6 +35,8 @@
 #include <unistd.h>
 #endif
 
+#include <time.h>
+
 #ifdef HAVE_IO_H
 #include <io.h>
 #endif
@@ -44,6 +46,7 @@
 #include <sys/stat.h>
 #include <errno.h>
 #include <fcntl.h>
+#include <signal.h>
 
 #ifdef NEED_SNPRINTF_H
 # ifdef HAVE_STDARG_H
 # include <netinet/in.h>
 #endif
 
-#include "ethereal.h"
+#ifdef HAVE_SYS_WAIT_H
+# include <sys/wait.h>
+#endif
+
+#include "gtk/main.h"
 #include "column.h"
-#include "menu.h"
+#include "gtk/menu.h"
 #include "packet.h"
 #include "print.h"
 #include "file.h"
 #include "util.h"
-#include "gtkpacket.h"
+#include "gtk/proto_draw.h"
 #include "dfilter.h"
 #include "timestamp.h"
+#include "conversation.h"
+
+#ifndef __RESOLV_H__
+#include "resolv.h"
+#endif
+
+#include "packet-atalk.h"
+
+#include "packet-ipv6.h"
 
 #include "packet-ncp.h"
 
 extern GtkWidget *packet_list, *prog_bar, *info_bar, *byte_view, *tree_view;
 extern guint      file_ctx;
-extern int       sync_mode;
 extern int        sync_pipe[];
 
 guint cap_input_id;
+gboolean auto_scroll_live = FALSE;
 
 static guint32 firstsec, firstusec;
 static guint32 prevsec, prevusec;
 
-static dfilter *rfcode = NULL; 
-
 static void wtap_dispatch_cb(u_char *, const struct wtap_pkthdr *, int,
     const u_char *);
 
 static void freeze_clist(capture_file *cf);
 static void thaw_clist(capture_file *cf);
 
-static gint dfilter_progress_cb(gpointer p);
+/* Update the progress bar this many times when reading a file. */
+#define N_PROGBAR_UPDATES      100
 
 int
 open_cap_file(char *fname, capture_file *cf) {
-  struct stat cf_stat;
-  FILE       *fh;
   wtap       *wth;
-  int        err;
+  int         err;
+  FILE_T      fh;
+  int         fd;
+  struct stat cf_stat;
 
-  /* First, make sure the file is valid */
-  if (stat(fname, &cf_stat)) {
-    err = errno;
+  wth = wtap_open_offline(fname, &err);
+  if (wth == NULL)
     goto fail;
-  }
-#ifndef WIN32
-  if (! S_ISREG(cf_stat.st_mode) && ! S_ISFIFO(cf_stat.st_mode)) {
-    err = OPEN_CAP_FILE_NOT_REGULAR;
-    goto fail;
-  }
-#endif
 
-  /* Next, try to open the file.
-     XXX - we only need to do this because "wtap_open_offline()"
-     doesn't return an indication of whether the open failed because
-     we don't have access to the file, or because it's not a valid
-     capture file, so we first have to open it with "fopen()" to
-     make sure we have access to it as a boring ordinary file. */
-  fh = fopen(fname, "r");
-  if (fh == NULL) {
+  /* Find the size of the file. */
+  fh = wtap_file(wth);
+  fd = wtap_fd(wth);
+  if (fstat(fd, &cf_stat) < 0) {
     err = errno;
-    goto fail;
-  }
-  fclose(fh);
-
-  /* Next, try to open it as a wiretap capture file. */
-  wth = wtap_open_offline(fname);
-  if (wth == NULL) {
-    /* XXX - we assume that, because we were able to open it above,
-       this must have failed because it's not a capture file in
-       a format we can read. */
-    err = OPEN_CAP_FILE_UNKNOWN_FORMAT;
+    wtap_close(wth);
     goto fail;
   }
 
@@ -145,11 +139,17 @@ open_cap_file(char *fname, capture_file *cf) {
      and fill in the information for this file. */
   close_cap_file(cf, info_bar, file_ctx);
 
+  /* Initialize the table of conversations. */
+  conversation_init();
+
   /* Initialize protocol-specific variables */
+  afs_init_protocol();
   ncp_init_protocol();
+  smb_init_protocol();
 
   cf->wth = wth;
-  cf->fh = wtap_file(cf->wth);
+  cf->fh = fh;
+  cf->filed = fd;
   cf->f_len = cf_stat.st_size;
 
   /* set the file name because we need it to set the follow stream filter */
@@ -162,6 +162,9 @@ open_cap_file(char *fname, capture_file *cf) {
   cf->esec      = 0;
   cf->eusec     = 0;
   cf->snap      = wtap_snapshot_length(cf->wth);
+  cf->update_progbar = FALSE;
+  cf->progbar_quantum = 0;
+  cf->progbar_nextstep = 0;
   firstsec = 0, firstusec = 0;
   prevsec = 0, prevusec = 0;
  
@@ -179,7 +182,7 @@ close_cap_file(capture_file *cf, void *w, guint context) {
   frame_data *fd, *fd_next;
 
   if (cf->fh) {
-    fclose(cf->fh);
+    file_close(cf->fh);
     cf->fh = NULL;
   }
   if (cf->wth) {
@@ -190,6 +193,10 @@ close_cap_file(capture_file *cf, void *w, guint context) {
     fd_next = fd->next;
     g_free(fd);
   }
+  if (cf->rfcode != NULL) {
+    dfilter_destroy(cf->rfcode);
+    cf->rfcode = NULL;
+  }
   cf->plist = NULL;
   cf->plist_end = NULL;
   unselect_packet(cf); /* nothing to select */
@@ -210,42 +217,44 @@ close_cap_file(capture_file *cf, void *w, guint context) {
 }
 
 int
-read_cap_file(char *fname, char *rfilter, capture_file *cf) {
+read_cap_file(capture_file *cf) {
   gchar  *name_ptr, *load_msg, *load_fmt = " Loading: %s...";
   gchar  *done_fmt = " File: %s  Drops: %d";
-  gchar  *err_fmt  = " Error: Could not load '%s'";
-  gint    timeout;
+  int     success;
+  int     err;
   size_t  msg_len;
+  char   *errmsg;
+  char    errmsg_errno[1024+1];
+  gchar   err_str[2048+1];
 
-  if ((name_ptr = (gchar *) strrchr(fname, '/')) == NULL)
-    name_ptr = fname;
+  if ((name_ptr = (gchar *) strrchr(cf->filename, '/')) == NULL)
+    name_ptr = cf->filename;
   else
     name_ptr++;
 
-  if (rfilter) {
-    rfcode = dfilter_new();
-    if (dfilter_compile(rfcode, rfilter) != 0) {
-      simple_dialog(ESD_TYPE_WARN, NULL,
-        "Unable to parse filter string \"%s\".", rfilter);
-      goto fail;
-    }
-  }
-
   load_msg = g_malloc(strlen(name_ptr) + strlen(load_fmt) + 2);
   sprintf(load_msg, load_fmt, name_ptr);
   gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx, load_msg);
-  
-  timeout = gtk_timeout_add(250, file_progress_cb, (gpointer) cf);
+
+  cf->update_progbar = TRUE;
+  /* Update the progress bar when it gets to this value. */
+  cf->progbar_nextstep = 0;
+  /* When we reach the value that triggers a progress bar update,
+     bump that value by this amount. */
+  cf->progbar_quantum = cf->f_len/N_PROGBAR_UPDATES;
 
   freeze_clist(cf);
-  wtap_loop(cf->wth, 0, wtap_dispatch_cb, (u_char *) cf);
+  proto_tree_is_visible = FALSE;
+  success = wtap_loop(cf->wth, 0, wtap_dispatch_cb, (u_char *) cf, &err);
   wtap_close(cf->wth);
   cf->wth = NULL;
-  cf->fh = fopen(fname, "r");
+  cf->filed = open(cf->filename, O_RDONLY);
+  cf->fh = filed_open(cf->filed, "r");
+  cf->unfiltered_count = cf->count;
   thaw_clist(cf);
-  
-  gtk_timeout_remove(timeout);
-  gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar), 0);
+
+  gtk_progress_set_activity_mode(GTK_PROGRESS(prog_bar), FALSE);
+  gtk_progress_set_value(GTK_PROGRESS(prog_bar), 0);
 
   gtk_statusbar_pop(GTK_STATUSBAR(info_bar), file_ctx);
 
@@ -260,30 +269,44 @@ read_cap_file(char *fname, char *rfilter, capture_file *cf) {
   gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx, load_msg);
   g_free(load_msg);
 
-/*  name_ptr[-1] = '\0';  Why is this here? It causes problems with capture files */
-
-  /* Remember the new read filter string. */
-  if (cf->rfilter != NULL)
-    g_free(cf->rfilter);
-  cf->rfilter = rfilter;
-
   /* Enable menu items that make sense if you have a capture. */
   set_menu_sensitivity("/File/Close", TRUE);
   set_menu_sensitivity("/File/Reload", TRUE);
   set_menu_sensitivity("/File/Print...", TRUE);
   set_menu_sensitivity("/Display/Options...", TRUE);
   set_menu_sensitivity("/Tools/Summary", TRUE);
-  return 0;
 
-fail:
-  msg_len = strlen(name_ptr) + strlen(err_fmt) + 2;
-  load_msg = g_malloc(msg_len);
-  snprintf(load_msg, msg_len, err_fmt, name_ptr);
-  gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx, load_msg);
-  g_free(load_msg);
-  if (rfilter != NULL)
-    g_free(rfilter);   /* assumed to be "g_strdup()"ed, if not null */
-  return -1;
+  if (!success) {
+    /* 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_CANT_READ:
+      errmsg = "An attempt to read from the 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.";
+      break;
+
+    case WTAP_ERR_BAD_RECORD:
+      errmsg = "The capture file appears to be damaged or corrupt.";
+      break;
+
+    default:
+      sprintf(errmsg_errno, "An error occurred while reading the"
+                              " capture file: %s.", wtap_strerror(err));
+      errmsg = errmsg_errno;
+      break;
+    }
+    snprintf(err_str, sizeof err_str, errmsg);
+    simple_dialog(ESD_TYPE_WARN, NULL, err_str);
+    return (err);
+  } else
+    return (0);
 }
 
 #ifdef HAVE_LIBPCAP
@@ -291,10 +314,17 @@ void
 cap_file_input_cb (gpointer data, gint source, GdkInputCondition condition) {
   
   capture_file *cf = (capture_file *)data;
-  char buffer[256], *p = buffer, *q = buffer;
+  char buffer[256+1], *p = buffer, *q = buffer;
   int  nread;
   int  to_read = 0;
   gboolean exit_loop = FALSE;
+  int  err;
+  int  wstatus;
+  int  wsignal;
+  char *msg;
+  char *sigmsg;
+  char sigmsg_buf[6+1+3+1];
+  char *coredumped;
 
   /* avoid reentrancy problems and stack overflow */
   gtk_input_remove(cap_input_id);
@@ -302,13 +332,117 @@ cap_file_input_cb (gpointer data, gint source, GdkInputCondition condition) {
   if ((nread = read(sync_pipe[0], buffer, 256)) <= 0) {
 
     /* The child has closed the sync pipe, meaning it's not going to be
-       capturing any more packets.  Read what remains of the capture file,
-       and stop capture (restore menu items) */
+       capturing any more packets.  Pick up its exit status, and
+       complain if it died of a signal. */
+    if (wait(&wstatus) != -1) {
+      /* XXX - are there any platforms on which we can run that *don't*
+         support POSIX.1's <sys/wait.h> and macros therein? */
+      wsignal = wstatus & 0177;
+      coredumped = "";
+      if (wstatus == 0177) {
+       /* It stopped, rather than exiting.  "Should not happen." */
+       msg = "stopped";
+       wsignal = (wstatus >> 8) & 0xFF;
+      } else {
+        msg = "terminated";
+        if (wstatus & 0200)
+          coredumped = " - core dumped";
+      }
+      if (wsignal != 0) {
+        switch (wsignal) {
+
+        case SIGHUP:
+          sigmsg = "Hangup";
+          break;
+
+        case SIGINT:
+          sigmsg = "Interrupted";
+          break;
+
+        case SIGQUIT:
+          sigmsg = "Quit";
+          break;
+
+        case SIGILL:
+          sigmsg = "Illegal instruction";
+          break;
+
+        case SIGTRAP:
+          sigmsg = "Trace trap";
+          break;
+
+        case SIGABRT:
+          sigmsg = "Abort";
+          break;
+
+        case SIGFPE:
+          sigmsg = "Arithmetic exception";
+          break;
+
+        case SIGKILL:
+          sigmsg = "Killed";
+          break;
+
+        case SIGBUS:
+          sigmsg = "Bus error";
+          break;
+
+        case SIGSEGV:
+          sigmsg = "Segmentation violation";
+          break;
+
+       /* http://metalab.unc.edu/pub/Linux/docs/HOWTO/GCC-HOWTO 
+               Linux is POSIX compliant.  These are not POSIX-defined signals ---
+                 ISO/IEC 9945-1:1990 (IEEE Std 1003.1-1990), paragraph B.3.3.1.1 sez:
+
+              ``The signals SIGBUS, SIGEMT, SIGIOT, SIGTRAP, and SIGSYS
+               were omitted from POSIX.1 because their behavior is
+               implementation dependent and could not be adequately catego-
+               rized.  Conforming implementations may deliver these sig-
+               nals, but must document the circumstances under which they
+               are delivered and note any restrictions concerning their
+               delivery.''
+       */
+
+       #ifdef SIGSYS
+        case SIGSYS:
+          sigmsg = "Bad system call";
+          break;
+       #endif
+
+        case SIGPIPE:
+          sigmsg = "Broken pipe";
+          break;
+
+        case SIGALRM:
+          sigmsg = "Alarm clock";
+          break;
+
+        case SIGTERM:
+          sigmsg = "Terminated";
+          break;
+
+        default:
+          sprintf(sigmsg_buf, "Signal %d", wsignal);
+          sigmsg = sigmsg_buf;
+          break;
+        }
+       simple_dialog(ESD_TYPE_WARN, NULL,
+               "Child capture process %s: %s%s", msg, sigmsg, coredumped);
+      }
+    }
+      
+    /* Read what remains of the capture file, and stop capture (restore
+       menu items) */
     gtk_clist_freeze(GTK_CLIST(packet_list));
 
-    wtap_loop(cf->wth, 0, wtap_dispatch_cb, (u_char *) cf);      
+    /* XXX - do something if this fails? */
+    wtap_loop(cf->wth, 0, wtap_dispatch_cb, (u_char *) cf, &err);
 
     thaw_clist(cf);
+    if (auto_scroll_live)
+      gtk_clist_moveto(GTK_CLIST(packet_list), 
+                      cf->plist_end->row, -1, 1.0, 1.0);
 
     wtap_close(cf->wth);
     cf->wth = NULL;
@@ -317,9 +451,7 @@ cap_file_input_cb (gpointer data, gint source, GdkInputCondition condition) {
     set_menu_sensitivity("/File/Save As...", TRUE);
     set_menu_sensitivity("/File/Print...", TRUE);
     set_menu_sensitivity("/File/Reload", TRUE);
-#ifdef HAVE_LIBPCAP
     set_menu_sensitivity("/Capture/Start...", TRUE);
-#endif
     set_menu_sensitivity("/Tools/Summary", TRUE);
     gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx, " File: <none>");
     return;
@@ -346,8 +478,11 @@ cap_file_input_cb (gpointer data, gint source, GdkInputCondition condition) {
   }
 
   gtk_clist_freeze(GTK_CLIST(packet_list));
-  wtap_loop(cf->wth, to_read, wtap_dispatch_cb, (u_char *) cf);      
+  /* XXX - do something if this fails? */
+  wtap_loop(cf->wth, to_read, wtap_dispatch_cb, (u_char *) cf, &err);
   gtk_clist_thaw(GTK_CLIST(packet_list));
+  if (auto_scroll_live)
+    gtk_clist_moveto(GTK_CLIST(packet_list), cf->plist_end->row, -1, 1.0, 1.0);
 
   /* restore pipe handler */
   cap_input_id = gtk_input_add_full (sync_pipe[0],
@@ -368,9 +503,7 @@ tail_cap_file(char *fname, capture_file *cf) {
 
     set_menu_sensitivity("/File/Open...", FALSE);
     set_menu_sensitivity("/Display/Options...", TRUE);
-#ifdef HAVE_LIBPCAP
     set_menu_sensitivity("/Capture/Start...", FALSE);
-#endif
 
     for (i = 0; i < cf->cinfo.num_cols; i++) {
       if (get_column_resize_type(cf->cinfo.col_fmt[i]) == RESIZE_LIVE)
@@ -383,7 +516,7 @@ tail_cap_file(char *fname, capture_file *cf) {
       }
     }
 
-    cf->fh = fopen(fname, "r");
+    cf->fh = file_open(fname, "r");
 
     cap_input_id = gtk_input_add_full (sync_pipe[0],
                                       GDK_INPUT_READ,
@@ -399,19 +532,19 @@ tail_cap_file(char *fname, capture_file *cf) {
   }
   return err;
 }
-#endif
+#endif /* HAVE_LIBPCAP */
 
 /* To do: Add check_col checks to the col_add* routines */
 
 static void
-col_add_abs_time(frame_data *fd, gint el)
+col_set_abs_time(frame_data *fd, int col)
 {
   struct tm *tmp;
   time_t then;
 
   then = fd->abs_secs;
   tmp = localtime(&then);
-  col_add_fstr(fd, el, "%02d:%02d:%02d.%04ld",
+  snprintf(fd->cinfo->col_data[col], COL_MAX_LEN, "%02d:%02d:%02d.%04ld",
     tmp->tm_hour,
     tmp->tm_min,
     tmp->tm_sec,
@@ -419,33 +552,243 @@ col_add_abs_time(frame_data *fd, gint el)
 }
 
 static void
-col_add_rel_time(frame_data *fd, gint el)
+col_set_rel_time(frame_data *fd, int col)
 {
-  col_add_fstr(fd, el, "%d.%06d", fd->rel_secs, fd->rel_usecs);
+  snprintf(fd->cinfo->col_data[col], COL_MAX_LEN, "%d.%06d", fd->rel_secs,
+    fd->rel_usecs);
 }
 
 static void
-col_add_delta_time(frame_data *fd, gint el)
+col_set_delta_time(frame_data *fd, int col)
 {
-  col_add_fstr(fd, el, "%d.%06d", fd->del_secs, fd->del_usecs);
+  snprintf(fd->cinfo->col_data[col], COL_MAX_LEN, "%d.%06d", fd->del_secs,
+    fd->del_usecs);
 }
 
 /* Add "command-line-specified" time. */
 static void
-col_add_cls_time(frame_data *fd)
+col_set_cls_time(frame_data *fd, int col)
 {
   switch (timestamp_type) {
     case ABSOLUTE:
-      col_add_abs_time(fd, COL_CLS_TIME);
+      col_set_abs_time(fd, col);
       break;
 
     case RELATIVE:
-      col_add_rel_time(fd, COL_CLS_TIME);
+      col_set_rel_time(fd, col);
       break;
 
     case DELTA:
-      col_add_delta_time(fd, COL_CLS_TIME);
+      col_set_delta_time(fd, col);
+      break;
+  }
+}
+
+static void
+col_set_addr(frame_data *fd, int col, address *addr, gboolean is_res)
+{
+  u_int ipv4_addr;
+  struct e_in6_addr ipv6_addr;
+  struct atalk_ddp_addr ddp_addr;
+
+  switch (addr->type) {
+
+  case AT_ETHER:
+    if (is_res)
+      strncpy(fd->cinfo->col_data[col], get_ether_name(addr->data), COL_MAX_LEN);
+    else
+      strncpy(fd->cinfo->col_data[col], ether_to_str(addr->data), COL_MAX_LEN);
+    break;
+
+  case AT_IPv4:
+    memcpy(&ipv4_addr, addr->data, sizeof ipv4_addr);
+    if (is_res)
+      strncpy(fd->cinfo->col_data[col], get_hostname(ipv4_addr), COL_MAX_LEN);
+    else
+      strncpy(fd->cinfo->col_data[col], ip_to_str(addr->data), COL_MAX_LEN);
+    break;
+
+  case AT_IPv6:
+    memcpy(&ipv6_addr.s6_addr, addr->data, sizeof ipv6_addr.s6_addr);
+    if (is_res)
+      strncpy(fd->cinfo->col_data[col], get_hostname6(&ipv6_addr), COL_MAX_LEN);
+    else
+      strncpy(fd->cinfo->col_data[col], ip6_to_str(&ipv6_addr), COL_MAX_LEN);
+    break;
+
+  case AT_IPX:
+    strncpy(fd->cinfo->col_data[col],
+      ipx_addr_to_str(pntohl(&addr->data[0]), &addr->data[4]), COL_MAX_LEN);
+    break;
+
+  case AT_SNA:
+    switch (addr->len) {
+
+    case 1:
+      snprintf(fd->cinfo->col_data[col], COL_MAX_LEN, "%04X", addr->data[0]);
+      break;
+
+    case 2:
+      snprintf(fd->cinfo->col_data[col], COL_MAX_LEN, "%04X",
+        pntohs(&addr->data[0]));
+      break;
+    }
+    break;
+
+  case AT_ATALK:
+    memcpy(&ddp_addr, addr->data, sizeof ddp_addr);
+    strncpy(fd->cinfo->col_data[col], atalk_addr_to_str(&ddp_addr),
+      COL_MAX_LEN);
+    break;
+
+  case AT_VINES:
+    strncpy(fd->cinfo->col_data[col], vines_addr_to_str(&addr->data[0]),
+      COL_MAX_LEN);
+    break;
+
+  default:
+    break;
+  }
+  fd->cinfo->col_data[col][COL_MAX_LEN - 1] = '\0';
+}
+
+static void
+col_set_port(frame_data *fd, int col, port_type ptype, guint32 port,
+               gboolean is_res)
+{
+  switch (ptype) {
+
+  case PT_TCP:
+    if (is_res)
+      strncpy(fd->cinfo->col_data[col], get_tcp_port(port), COL_MAX_LEN);
+    else
+      snprintf(fd->cinfo->col_data[col], COL_MAX_LEN, "%u", port);
+    break;
+
+  case PT_UDP:
+    if (is_res)
+      strncpy(fd->cinfo->col_data[col], get_udp_port(port), COL_MAX_LEN);
+    else
+      snprintf(fd->cinfo->col_data[col], COL_MAX_LEN, "%u", port);
+    break;
+
+  default:
+    break;
+  }
+  fd->cinfo->col_data[col][COL_MAX_LEN - 1] = '\0';
+}
+
+static void
+fill_in_columns(frame_data *fd)
+{
+  int i;
+
+  for (i = 0; i < fd->cinfo->num_cols; i++) {
+    switch (fd->cinfo->col_fmt[i]) {
+
+    case COL_NUMBER:
+      snprintf(fd->cinfo->col_data[i], COL_MAX_LEN, "%u", fd->num);
+      break;
+
+    case COL_CLS_TIME:
+      col_set_cls_time(fd, i);
+      break;
+
+    case COL_ABS_TIME:
+      col_set_abs_time(fd, i);
+      break;
+
+    case COL_REL_TIME:
+      col_set_rel_time(fd, i);
+      break;
+
+    case COL_DELTA_TIME:
+      col_set_delta_time(fd, i);
+      break;
+
+    case COL_DEF_SRC:
+    case COL_RES_SRC:  /* COL_DEF_SRC is currently just like COL_RES_SRC */
+      col_set_addr(fd, i, &pi.src, TRUE);
+      break;
+
+    case COL_UNRES_SRC:
+      col_set_addr(fd, i, &pi.src, FALSE);
       break;
+
+    case COL_DEF_DL_SRC:
+    case COL_RES_DL_SRC:
+      col_set_addr(fd, i, &pi.dl_src, TRUE);
+      break;
+
+    case COL_UNRES_DL_SRC:
+      col_set_addr(fd, i, &pi.dl_src, FALSE);
+      break;
+
+    case COL_DEF_NET_SRC:
+    case COL_RES_NET_SRC:
+      col_set_addr(fd, i, &pi.net_src, TRUE);
+      break;
+
+    case COL_UNRES_NET_SRC:
+      col_set_addr(fd, i, &pi.net_src, FALSE);
+      break;
+
+    case COL_DEF_DST:
+    case COL_RES_DST:  /* COL_DEF_DST is currently just like COL_RES_DST */
+      col_set_addr(fd, i, &pi.dst, TRUE);
+      break;
+
+    case COL_UNRES_DST:
+      col_set_addr(fd, i, &pi.dst, FALSE);
+      break;
+
+    case COL_DEF_DL_DST:
+    case COL_RES_DL_DST:
+      col_set_addr(fd, i, &pi.dl_dst, TRUE);
+      break;
+
+    case COL_UNRES_DL_DST:
+      col_set_addr(fd, i, &pi.dl_dst, FALSE);
+      break;
+
+    case COL_DEF_NET_DST:
+    case COL_RES_NET_DST:
+      col_set_addr(fd, i, &pi.net_dst, TRUE);
+      break;
+
+    case COL_UNRES_NET_DST:
+      col_set_addr(fd, i, &pi.net_dst, FALSE);
+      break;
+
+    case COL_DEF_SRC_PORT:
+    case COL_RES_SRC_PORT:     /* COL_DEF_SRC_PORT is currently just like COL_RES_SRC_PORT */
+      col_set_port(fd, i, pi.ptype, pi.srcport, TRUE);
+      break;
+
+    case COL_UNRES_SRC_PORT:
+      col_set_port(fd, i, pi.ptype, pi.srcport, FALSE);
+      break;
+
+    case COL_DEF_DST_PORT:
+    case COL_RES_DST_PORT:     /* COL_DEF_DST_PORT is currently just like COL_RES_DST_PORT */
+      col_set_port(fd, i, pi.ptype, pi.destport, TRUE);
+      break;
+
+    case COL_UNRES_DST_PORT:
+      col_set_port(fd, i, pi.ptype, pi.destport, FALSE);
+      break;
+
+    case COL_PROTOCOL: /* currently done by dissectors */
+    case COL_INFO:     /* currently done by dissectors */
+      break;
+
+    case COL_PACKET_LENGTH:
+      snprintf(fd->cinfo->col_data[i], COL_MAX_LEN, "%d", fd->pkt_len);
+      break;
+
+    case NUM_COL_FMTS: /* keep compiler happy - shouldn't get here */
+      break;
+    }
   }
 }
 
@@ -453,8 +796,12 @@ static void
 add_packet_to_packet_list(frame_data *fdata, capture_file *cf, const u_char *buf)
 {
   gint          i, row;
+  gint         crow;
+  gint                 color;
   proto_tree   *protocol_tree;
 
+  fdata->num = cf->count;
+
   /* If we don't have the time stamp of the first packet in the
      capture, it's because this is the first packet.  Save the time
      stamp of this packet as the time stamp of the first packet. */
@@ -477,21 +824,38 @@ add_packet_to_packet_list(frame_data *fdata, capture_file *cf, const u_char *buf
     fdata->cinfo->col_data[i][0] = '\0';
   }
 
-  /* Apply the display filter */
-  if (DFILTER_CONTAINS_FILTER(cf->dfcode)) {
+  /* Apply the filters */
+  if (cf->dfcode != NULL ||
+      CFILTERS_CONTAINS_FILTER(cf)) {
        protocol_tree = proto_tree_create_root();
        dissect_packet(buf, fdata, protocol_tree);
-       fdata->passed_dfilter = dfilter_apply(cf->dfcode, protocol_tree, cf->pd);
+       if (cf->dfcode != NULL)
+               fdata->passed_dfilter = dfilter_apply(cf->dfcode, protocol_tree, cf->pd);
+       else
+               fdata->passed_dfilter = TRUE;
+       /* Apply color filters. */
+       color = -1;
+        for(crow = 0; cf->colors->num_of_filters && 
+             crow < cf->colors->num_of_filters; crow++) {
+
+            if(color_filter(cf,crow)->c_colorfilter == NULL) {
+               continue;
+           }
+            if(dfilter_apply(color_filter(cf,crow)->c_colorfilter, protocol_tree,
+                cf->pd)){
+                color = crow;
+               break;
+            }
+        }
+
        proto_tree_free(protocol_tree);
   }
   else {
        dissect_packet(buf, fdata, NULL);
        fdata->passed_dfilter = TRUE;
+       color = -1;
   }
   if (fdata->passed_dfilter) {
-    if (check_col(fdata, COL_NUMBER))
-      col_add_fstr(fdata, COL_NUMBER, "%d", cf->count);
-
     /* If we don't have the time stamp of the previous displayed packet,
        it's because this is the first displayed packet.  Save the time
        stamp of this packet as the time stamp of the previous displayed
@@ -517,26 +881,25 @@ add_packet_to_packet_list(frame_data *fdata, capture_file *cf, const u_char *buf
     prevsec = fdata->abs_secs;
     prevusec = fdata->abs_usecs;
 
-    /* Set any time stamp columns. */
-    if (check_col(fdata, COL_CLS_TIME))
-      col_add_cls_time(fdata);
-    if (check_col(fdata, COL_ABS_TIME))
-      col_add_abs_time(fdata, COL_ABS_TIME);
-    if (check_col(fdata, COL_REL_TIME))
-      col_add_rel_time(fdata, COL_REL_TIME);
-    if (check_col(fdata, COL_DELTA_TIME))
-      col_add_delta_time(fdata, COL_DELTA_TIME);
-
-    if (check_col(fdata, COL_PACKET_LENGTH))
-      col_add_fstr(fdata, COL_PACKET_LENGTH, "%d", fdata->pkt_len);
+    fill_in_columns(fdata);
 
     row = gtk_clist_append(GTK_CLIST(packet_list), fdata->cinfo->col_data);
     fdata->row = row;
 
+    if (cf->colors->color_filters && (color != -1)){
+        gtk_clist_set_background(GTK_CLIST(packet_list), row,
+                   &(color_filter(cf,color)->bg_color));
+        gtk_clist_set_foreground(GTK_CLIST(packet_list), row,
+                   &(color_filter(cf,color)->fg_color));
+    } else {
+        gtk_clist_set_background(GTK_CLIST(packet_list), row, &WHITE);
+        gtk_clist_set_foreground(GTK_CLIST(packet_list), row, &BLACK);
+    }
+
     /* If this was the selected packet, remember the row it's in, so
        we can re-select it.  ("selected_packet" is 0-origin, as it's
-       a GList index; "count", however, is 1-origin.) */
-    if (cf->selected_packet == cf->count - 1)
+       a GList index; "num", however, is 1-origin.) */
+    if (cf->selected_packet == fdata->num - 1)
       cf->selected_row = row;
   } else
     fdata->row = -1;   /* not in the display */
@@ -551,9 +914,28 @@ wtap_dispatch_cb(u_char *user, const struct wtap_pkthdr *phdr, int offset,
   int           passed;
   proto_tree   *protocol_tree;
   frame_data   *plist_end;
-
-  while (gtk_events_pending())
-    gtk_main_iteration();
+  int file_pos;
+  float prog_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.
+     
+     Do so only if we were told to do so; when reading a capture file
+     being updated by a live capture, we don't do so (as we're not
+     "done" until the capture stops, so we don't know how close to
+     "done" we are. */
+
+  if (cf->update_progbar && offset >= cf->progbar_nextstep) {
+      file_pos = lseek(cf->filed, 0, SEEK_CUR);
+      prog_val = (gfloat) file_pos / (gfloat) cf->f_len;
+      gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar), prog_val);
+      cf->progbar_nextstep += cf->progbar_quantum;
+      while (gtk_events_pending())
+      gtk_main_iteration();
+  }
 
   /* Allocate the next list entry, and add it to the list. */
   fdata = (frame_data *) g_malloc(sizeof(frame_data));
@@ -565,17 +947,15 @@ wtap_dispatch_cb(u_char *user, const struct wtap_pkthdr *phdr, int offset,
   fdata->lnk_t = phdr->pkt_encap;
   fdata->abs_secs  = phdr->ts.tv_sec;
   fdata->abs_usecs = phdr->ts.tv_usec;
-  fdata->flags = phdr->flags;
+  fdata->pseudo_header = phdr->pseudo_header;
   fdata->cinfo = NULL;
 
   passed = TRUE;
-  if (rfcode) {
-         if (DFILTER_CONTAINS_FILTER(rfcode)) {
-           protocol_tree = proto_tree_create_root();
-           dissect_packet(buf, fdata, protocol_tree);
-           passed = dfilter_apply(rfcode, protocol_tree, cf->pd);
-           proto_tree_free(protocol_tree);
-         }
+  if (cf->rfcode) {
+    protocol_tree = proto_tree_create_root();
+    dissect_packet(buf, fdata, protocol_tree);
+    passed = dfilter_apply(cf->rfcode, protocol_tree, cf->pd);
+    proto_tree_free(protocol_tree);
   }   
   if (passed) {
     plist_end = cf->plist_end;
@@ -592,25 +972,56 @@ wtap_dispatch_cb(u_char *user, const struct wtap_pkthdr *phdr, int offset,
 }
 
 void
-filter_packets(capture_file *cf)
+filter_packets(capture_file *cf, gchar *dftext)
 {
-/*  gint timeout;*/
-  frame_data *fd;
+  dfilter *dfcode;
 
-  if (cf->dfilter == NULL) {
-       dfilter_clear_filter(cf->dfcode);
-  }
-  else {
+  if (dftext == NULL) {
+    /* The new filter is an empty filter (i.e., display all packets). */
+    dfcode = NULL;
+  else {
     /*
-     * Compile the filter.
+     * We have a filter; try to compile it.
      */
-    if (dfilter_compile(cf->dfcode, cf->dfilter) != 0) {
-      simple_dialog(ESD_TYPE_WARN, NULL,
-      "Unable to parse filter string \"%s\".", cf->dfilter);
+    if (dfilter_compile(dftext, &dfcode) != 0) {
+      /* The attempt failed; report an error. */
+      simple_dialog(ESD_TYPE_WARN, NULL, dfilter_error_msg);
       return;
     }
+
+    /* Was it empty? */
+    if (dfcode == NULL) {
+      /* Yes - free the filter text, and set it to null. */
+      g_free(dftext);
+      dftext = NULL;
+    }
   }
 
+  /* We have a valid filter.  Replace the current filter. */
+  if (cf->dfilter != NULL)
+    g_free(cf->dfilter);
+  cf->dfilter = dftext;
+  if (cf->dfcode != NULL)
+    dfilter_destroy(cf->dfcode);
+  cf->dfcode = dfcode;
+
+  /* Now go through the list of packets we've read from the capture file,
+     applying the current display filter, and, if the packet passes the
+     display filter, add it to the summary display, appropriately
+     colored.  (That's how we colorize the display - it's like filtering
+     the display, only we don't install a new filter.) */
+  colorize_packets(cf);
+}
+
+void
+colorize_packets(capture_file *cf)
+{
+  frame_data *fd;
+  guint32 progbar_quantum;
+  guint32 progbar_nextstep;
+
+  gtk_progress_set_activity_mode(GTK_PROGRESS(prog_bar), FALSE);
+
   /* Freeze the packet list while we redo it, so we don't get any
      screen updates while it happens. */
   gtk_clist_freeze(GTK_CLIST(packet_list));
@@ -632,20 +1043,41 @@ filter_packets(capture_file *cf)
   cf->unfiltered_count = cf->count;
   cf->count = 0;
 
-/*  timeout = gtk_timeout_add(250, dfilter_progress_cb, cf);*/
+  proto_tree_is_visible = FALSE;
+
+  /* Update the progress bar when it gets to this value. */
+  progbar_nextstep = 0;
+  /* When we reach the value that triggers a progress bar update,
+     bump that value by this amount. */
+  progbar_quantum = cf->unfiltered_count/N_PROGBAR_UPDATES;
+  gtk_progress_bar_set_orientation(GTK_PROGRESS_BAR(prog_bar), GTK_PROGRESS_LEFT_TO_RIGHT);
+
   for (fd = cf->plist; fd != NULL; fd = fd->next) {
+    /* 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 (cf->count >= progbar_nextstep) {
+      /* let's not divide by zero. I should never be started
+       * with unfiltered_count == 0, so let's assert that
+       */
+      g_assert(cf->unfiltered_count > 0);
+
+       gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar),
+               (gfloat) cf->count / cf->unfiltered_count);
+
+      progbar_nextstep += progbar_quantum;
+      while (gtk_events_pending())
+        gtk_main_iteration();
+    }
+
     cf->count++;
 
-    fseek(cf->fh, fd->file_off, SEEK_SET);
-    fread(cf->pd, sizeof(guint8), fd->cap_len, cf->fh);
+    wtap_seek_read (cf-> cd_t, cf->fh, fd->file_off, cf->pd, fd->cap_len);
 
     add_packet_to_packet_list(fd, cf, cf->pd);
-
-    if (cf->count % 20 == 0) {
-      dfilter_progress_cb(cf);
-    }
   }
-/*  gtk_timeout_remove(timeout);*/
  
   gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar), 0);
 
@@ -661,34 +1093,20 @@ filter_packets(capture_file *cf)
   gtk_clist_thaw(GTK_CLIST(packet_list));
 }
 
-/* Update the progress bar */
-static gint
-dfilter_progress_cb(gpointer p) {
-  capture_file *cf = (capture_file*)p;
-
-  /* let's not divide by zero. I should never be started
-   * with unfiltered_count == 0, so let's assert that
-   */
-  g_assert(cf->unfiltered_count > 0);
-
-  gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar),
-    (gfloat) cf->count / cf->unfiltered_count);
-
-  /* Have GTK+ repaint what is pending */
-  while (gtk_events_pending ()) {
-         gtk_main_iteration();
-  }
-  return TRUE;
-}
-
-
 int
-print_packets(capture_file *cf, int to_file, const char *dest)
+print_packets(capture_file *cf, print_args_t *print_args)
 {
+  int         i;
   frame_data *fd;
+  guint32     progbar_quantum;
+  guint32     progbar_nextstep;
+  guint32     count;
   proto_tree *protocol_tree;
+  gint       *col_widths = NULL;
+  gint        data_width;
+  gboolean    print_separator;
 
-  cf->print_fh = open_print_dest(to_file, dest);
+  cf->print_fh = open_print_dest(print_args->to_file, print_args->dest);
   if (cf->print_fh == NULL)
     return FALSE;      /* attempt to open destination failed */
 
@@ -701,29 +1119,127 @@ print_packets(capture_file *cf, int to_file, const char *dest)
   print_preamble(cf->print_fh);
 #endif
 
-  /* Iterate through the list of packets, printing each of them.  */
-  cf->count = 0;
+  if (print_args->print_summary) {
+    /* We're printing packet summaries.
+
+       Find the widths for each of the columns - maximum of the
+       width of the title and the width of the data - and print
+       the column titles. */
+    col_widths = (gint *) g_malloc(sizeof(gint) * cf->cinfo.num_cols);
+    for (i = 0; i < cf->cinfo.num_cols; i++) {
+      /* Don't pad the last column. */
+      if (i == cf->cinfo.num_cols - 1)
+        col_widths[i] = 0;
+      else {
+        col_widths[i] = strlen(cf->cinfo.col_title[i]);
+        data_width = get_column_char_width(get_column_format(i));
+        if (data_width > col_widths[i])
+          col_widths[i] = data_width;
+      }
+
+      /* Right-justify the packet number column. */
+      if (cf->cinfo.col_fmt[i] == COL_NUMBER)
+        fprintf(cf->print_fh, "%*s", col_widths[i], cf->cinfo.col_title[i]);
+      else
+        fprintf(cf->print_fh, "%-*s", col_widths[i], cf->cinfo.col_title[i]);
+      if (i == cf->cinfo.num_cols - 1)
+        fputc('\n', cf->print_fh);
+      else
+        fputc(' ', cf->print_fh);
+    }
+  }
+
+  print_separator = FALSE;
+  proto_tree_is_visible = TRUE;
+
+  /* Update the progress bar when it gets to this value. */
+  progbar_nextstep = 0;
+  /* When we reach the value that triggers a progress bar update,
+     bump that value by this amount. */
+  progbar_quantum = cf->unfiltered_count/N_PROGBAR_UPDATES;
+  /* Count of packets we've looked at. */
+  count = 0;
+
+  /* Iterate through the list of packets, printing the packets that
+     were selected by the current display filter.  */
   for (fd = cf->plist; fd != NULL; fd = fd->next) {
-    cf->count++;
+    /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
+       when we update it, we have to run the GTK+ main loop to get it
+       to repaint what's pending, and doing so may involve an "ioctl()"
+       to see if there's any pending input from an X server, and doing
+       that for every packet can be costly, especially on a big file. */
+    if (count >= progbar_nextstep) {
+      /* let's not divide by zero. I should never be started
+       * with unfiltered_count == 0, so let's assert that
+       */
+      g_assert(cf->unfiltered_count > 0);
+
+      gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar),
+        (gfloat) count / cf->unfiltered_count);
+      progbar_nextstep += progbar_quantum;
+      while (gtk_events_pending())
+        gtk_main_iteration();
+    }
+    count++;
+
+    if (fd->passed_dfilter) {
+      wtap_seek_read (cf->cd_t, cf->fh, fd->file_off, cf->pd, fd->cap_len);
+      if (print_args->print_summary) {
+        /* Fill in the column information, but don't bother creating
+           the logical protocol tree. */
+        fd->cinfo = &cf->cinfo;
+        for (i = 0; i < fd->cinfo->num_cols; i++) {
+          fd->cinfo->col_data[i][0] = '\0';
+        }
+        dissect_packet(cf->pd, fd, NULL);
+        fill_in_columns(fd);
+        for (i = 0; i < cf->cinfo.num_cols; i++) {
+          /* Right-justify the packet number column. */
+          if (cf->cinfo.col_fmt[i] == COL_NUMBER)
+            fprintf(cf->print_fh, "%*s", col_widths[i], cf->cinfo.col_data[i]);
+          else
+            fprintf(cf->print_fh, "%-*s", col_widths[i], cf->cinfo.col_data[i]);
+          if (i == cf->cinfo.num_cols - 1)
+            fputc('\n', cf->print_fh);
+          else
+            fputc(' ', cf->print_fh);
+        }
+      } else {
+        if (print_separator)
+          fputc('\n', cf->print_fh);
 
-    fseek(cf->fh, fd->file_off, SEEK_SET);
-    fread(cf->pd, sizeof(guint8), fd->cap_len, cf->fh);
+        /* Create the logical protocol tree. */
+        protocol_tree = proto_tree_create_root();
+        dissect_packet(cf->pd, fd, protocol_tree);
 
-    /* create the logical protocol tree */
-    protocol_tree = proto_tree_create_root();
-    dissect_packet(cf->pd, fd, protocol_tree);
+        /* Print the information in that tree. */
+        proto_tree_print(FALSE, print_args, (GNode *)protocol_tree,
+                       cf->pd, fd, cf->print_fh);
 
-    /* Print the packet */
-    proto_tree_print(cf->count, (GNode *)protocol_tree, cf->pd, fd, cf->print_fh);
+        proto_tree_free(protocol_tree);
 
-    proto_tree_free(protocol_tree);
+       if (print_args->print_hex) {
+         /* Print the full packet data as hex. */
+         print_hex_data(cf->print_fh, cf->pd, fd->cap_len);
+       }
+
+        /* Print a blank line if we print anything after this. */
+        print_separator = TRUE;
+      }
+    }
   }
 
+  if (col_widths != NULL)
+    g_free(col_widths);
+
 #if 0
   print_finale(cf->print_fh);
 #endif
 
-  close_print_dest(to_file, cf->print_fh);
+  close_print_dest(print_args->to_file, cf->print_fh);
+  gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar), 0);
+
   cf->print_fh = NULL;
   return TRUE;
 }
@@ -758,14 +1274,12 @@ change_time_formats(capture_file *cf)
       if (check_col(fd, COL_CLS_TIME)) {
         /* There are columns that show the time in the "command-line-specified"
            format; update them. */
-        for (i = 0; i < cf->cinfo.num_cols; i++) {
-          cf->cinfo.col_data[i][0] = '\0';
-        }
-        col_add_cls_time(fd);
         for (i = 0; i < cf->cinfo.num_cols; i++) {
           if (cf->cinfo.fmt_matx[i][COL_CLS_TIME]) {
             /* This is one of the columns that shows the time in
                "command-line-specified" format; update it. */
+            cf->cinfo.col_data[i][0] = '\0';
+            col_set_cls_time(fd, i);
             gtk_clist_set_text(GTK_CLIST(packet_list), fd->row, i,
                          cf->cinfo.col_data[i]);
          }
@@ -791,6 +1305,9 @@ change_time_formats(capture_file *cf)
 static void
 clear_tree_and_hex_views(void)
 {
+  GList *selection;
+  GtkWidget *tmp_item;
+
   /* Clear the hex dump. */
   gtk_text_freeze(GTK_TEXT(byte_view));
   gtk_text_set_point(GTK_TEXT(byte_view), 0);
@@ -798,11 +1315,28 @@ clear_tree_and_hex_views(void)
     gtk_text_get_length(GTK_TEXT(byte_view)));
   gtk_text_thaw(GTK_TEXT(byte_view));
 
-  /* Clear the protocol tree view. */
-  gtk_tree_clear_items(GTK_TREE(tree_view), 0,
-    g_list_length(GTK_TREE(tree_view)->children));
+  /* Deselect any selected tree item. gtktree.c should
+   * do this when we clear_items, but it doesn't. I copied
+   * this while() loop from gtktree.c, gtk_real_tree_select_child()
+   */
+  if (GTK_TREE(tree_view)->root_tree) {
+         selection = GTK_TREE(tree_view)->root_tree->selection;
+         while (selection) {
+                 tmp_item = selection->data;
+                 gtk_tree_item_deselect(GTK_TREE_ITEM(tmp_item));
+                 gtk_widget_unref(tmp_item);
+                 selection = selection->next;
+         }
+         g_list_free(GTK_TREE(tree_view)->root_tree->selection);
+         GTK_TREE(tree_view)->root_tree->selection = NULL;
+  }
+
+  /* Clear the protocol tree view. The length arg of -1
+   * means to clear all items up to the end. */
+  gtk_tree_clear_items(GTK_TREE(tree_view), 0, -1);
 }
 
+
 /* Select the packet on a given row. */
 void
 select_packet(capture_file *cf, int row)
@@ -822,19 +1356,22 @@ select_packet(capture_file *cf, int row)
     if (fd->row == row)
       break;
   }
+
+  g_assert(fd != NULL);
+
   cf->fd = fd;
 
   /* Remember the ordinal number of that frame. */
   cf->selected_packet = i;
 
   /* Get the data in that frame. */
-  fseek(cf->fh, cf->fd->file_off, SEEK_SET);
-  fread(cf->pd, sizeof(guint8), cf->fd->cap_len, cf->fh);
+  wtap_seek_read (cf-> cd_t, cf->fh, fd->file_off, cf->pd, fd->cap_len);
 
   /* Create the logical protocol tree. */
   if (cf->protocol_tree)
       proto_tree_free(cf->protocol_tree);
   cf->protocol_tree = proto_tree_create_root();
+  proto_tree_is_visible = TRUE;
   dissect_packet(cf->pd, cf->fd, cf->protocol_tree);
 
   /* Display the GUI protocol tree and hex dump. */
@@ -845,6 +1382,8 @@ select_packet(capture_file *cf, int row)
 
   /* A packet is selected, so "File/Print Packet" has something to print. */
   set_menu_sensitivity("/File/Print Packet", TRUE);
+  set_menu_sensitivity("/Display/Collapse All", TRUE);
+  set_menu_sensitivity("/Display/Expand All", TRUE);
 }
 
 /* Unselect the selected packet, if any. */
@@ -865,6 +1404,8 @@ unselect_packet(capture_file *cf)
 
   /* No packet is selected, so "File/Print Packet" has nothing to print. */
   set_menu_sensitivity("/File/Print Packet", FALSE);
+  set_menu_sensitivity("/Display/Collapse All", FALSE);
+  set_menu_sensitivity("/Display/Expand All", FALSE);
 }
 
 static void
@@ -1001,14 +1542,31 @@ file_open_error_message(int err, int for_writing)
 
   switch (err) {
 
-  case OPEN_CAP_FILE_NOT_REGULAR:
+  case WTAP_ERR_NOT_REGULAR_FILE:
     errmsg = "The file \"%s\" is invalid.";
     break;
 
-  case OPEN_CAP_FILE_UNKNOWN_FORMAT:
+  case WTAP_ERR_FILE_UNKNOWN_FORMAT:
+  case WTAP_ERR_UNSUPPORTED:
     errmsg = "The file \"%s\" is not a capture file in a format Ethereal understands.";
     break;
 
+  case WTAP_ERR_BAD_RECORD:
+    errmsg = "The file \"%s\" appears to be damaged or corrupt.";
+    break;
+
+  case WTAP_ERR_CANT_OPEN:
+    if (for_writing)
+      errmsg = "The file \"%s\" could not be created for some unknown reason.";
+    else
+      errmsg = "The file \"%s\" could not be opened for some unknown reason.";
+    break;
+
+  case WTAP_ERR_SHORT_READ:
+    errmsg = "The file \"%s\" appears to have been cut short"
+             " in the middle of a packet.";
+    break;
+
   case ENOENT:
     if (for_writing)
       errmsg = "The path to the file \"%s\" does not exist.";
@@ -1020,11 +1578,12 @@ file_open_error_message(int err, int for_writing)
     if (for_writing)
       errmsg = "You do not have permission to create or write to the file \"%s\".";
     else
-      errmsg = "You do not have permission to open the file \"%s\".";
+      errmsg = "You do not have permission to read the file \"%s\".";
     break;
 
   default:
-    sprintf(errmsg_errno, "The file \"%%s\" could not be opened: %s.", strerror(err));
+    sprintf(errmsg_errno, "The file \"%%s\" could not be opened: %s.",
+                               wtap_strerror(err));
     errmsg = errmsg_errno;
     break;
   }
@@ -1036,7 +1595,8 @@ file_read_error_message(int err)
 {
   static char errmsg_errno[1024+1];
 
-  sprintf(errmsg_errno, "An error occurred while reading from the file \"%%s\": %s.", strerror(err));
+  sprintf(errmsg_errno, "An error occurred while reading from the file \"%%s\": %s.",
+                               wtap_strerror(err));
   return errmsg_errno;
 }
 
@@ -1059,7 +1619,8 @@ file_write_error_message(int err)
 #endif
 
   default:
-    sprintf(errmsg_errno, "An error occurred while writing to the file \"%%s\": %s.", strerror(err));
+    sprintf(errmsg_errno, "An error occurred while writing to the file \"%%s\": %s.",
+                               wtap_strerror(err));
     errmsg = errmsg_errno;
     break;
   }