Add a "-p" command-line option, and a checkbox in the "Capture
[obnox/wireshark/wip.git] / gtk / capture_dlg.c
index f69605de0c627d96b01cb99b789c237272b8e50d..f7f25cc9c179284e767dc998c90d91d2e30594fa 100644 (file)
@@ -1,7 +1,7 @@
 /* capture_dlg.c
  * Routines for packet capture windows
  *
- * $Id: capture_dlg.c,v 1.16 2000/01/06 05:09:01 guy Exp $
+ * $Id: capture_dlg.c,v 1.33 2000/09/15 05:32:48 guy Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@zing.org>
 
 #include <time.h>
 
-#ifdef HAVE_SYS_SOCKET_H
-#include <sys/socket.h>
-#endif
-
-#ifdef HAVE_SYS_IOCTL_H
-#include <sys/ioctl.h>
-#endif
-
-#ifdef HAVE_NET_IF_H
-#include <net/if.h>
-#endif
-
-#include <signal.h>
-#include <errno.h>
-
 #ifdef NEED_SNPRINTF_H
-# ifdef HAVE_STDARG_H
-#  include <stdarg.h>
-# else
-#  include <varargs.h>
-# endif
 # include "snprintf.h"
 #endif
 
-#ifdef HAVE_SYS_SOCKIO_H
-# include <sys/sockio.h>
-#endif
-
-#include <wiretap/wtap.h>
 #include "capture.h"
 #include "globals.h"
 #include "main.h"
+#include "ui_util.h"
 #include "capture_dlg.h"
-#include "prefs_dlg.h"
+#include "filter_prefs.h"
 #include "simple_dialog.h"
+#include "dlg_utils.h"
+#include "util.h"
 
 /* Capture callback data keys */
-#define E_CAP_IFACE_KEY    "cap_iface"
-#define E_CAP_FILT_KEY     "cap_filter_te"
-#define E_CAP_FILE_TE_KEY  "cap_file_te"
-#define E_CAP_COUNT_KEY    "cap_count"
-#define E_CAP_SNAP_KEY     "cap_snap"
-#define E_CAP_SYNC_KEY     "cap_sync"
-#define E_CAP_RESOLVE_KEY  "cap_resolve"
-
-static GList*
-get_interface_list();
+#define E_CAP_IFACE_KEY       "cap_iface"
+#define E_CAP_FILT_KEY        "cap_filter_te"
+#define E_CAP_FILE_TE_KEY     "cap_file_te"
+#define E_CAP_COUNT_KEY       "cap_count"
+#define E_CAP_SNAP_KEY        "cap_snap"
+#define E_CAP_PROMISC_KEY     "cap_promisc"
+#define E_CAP_SYNC_KEY        "cap_sync"
+#define E_CAP_AUTO_SCROLL_KEY "cap_auto_scroll"
+#define E_CAP_RESOLVE_KEY     "cap_resolve"
+
+#define E_FS_CALLER_PTR_KEY       "fs_caller_ptr"
+#define E_FILE_SEL_DIALOG_PTR_KEY "file_sel_dialog_ptr"
 
 static void
 capture_prep_file_cb(GtkWidget *w, gpointer te);
@@ -98,6 +78,9 @@ cap_prep_fs_ok_cb(GtkWidget *w, gpointer data);
 static void
 cap_prep_fs_cancel_cb(GtkWidget *w, gpointer data);
 
+static void
+cap_prep_fs_destroy_cb(GtkWidget *win, gpointer data);
+
 static void
 capture_prep_ok_cb(GtkWidget *ok_bt, gpointer parent_w);
 
@@ -105,111 +88,127 @@ static void
 capture_prep_close_cb(GtkWidget *close_bt, gpointer parent_w);
 
 static void
-search_for_if_cb(gpointer data, gpointer user_data);
+capture_prep_destroy_cb(GtkWidget *win, gpointer user_data);
 
-static void
-free_if_cb(gpointer data, gpointer user_data);
+/*
+ * Keep a static pointer to the current "Capture Preferences" window, if
+ * any, so that if somebody tries to do "Capture:Start" while there's
+ * already a "Capture Preferences" window up, we just pop up the existing
+ * one, rather than creating a new one.
+ */
+static GtkWidget *cap_open_w;
 
 void
 capture_prep_cb(GtkWidget *w, gpointer d)
 {
-  GtkWidget     *cap_open_w, *if_cb, *if_lb,
-                *count_lb, *count_cb, *main_vb, *if_hb, *count_hb,
-                *filter_hb, *filter_bt, *filter_te,
-                *file_hb, *file_bt, *file_te,
-                *caplen_hb,
+  GtkWidget     *if_cb, *if_lb,
+                *count_lb, *count_cb, *main_vb,
+                *filter_bt, *filter_te,
+                *file_bt, *file_te,
+                *caplen_hb, *table,
                 *bbox, *ok_bt, *cancel_bt, *snap_lb,
-                *snap_sb, *sync_cb, *resolv_cb;
+                *snap_sb, *promisc_cb, *sync_cb, *auto_scroll_cb, *resolv_cb;
+  GtkAccelGroup *accel_group;
   GtkAdjustment *adj;
   GList         *if_list, *count_list = NULL;
   gchar         *count_item1 = "0 (Infinite)", count_item2[16];
+  int           err;
+  char          err_str[PCAP_ERRBUF_SIZE];
 
-  if_list = get_interface_list();
+  if (cap_open_w != NULL) {
+    /* There's already a "Capture Preferences" dialog box; reactivate it. */
+    reactivate_window(cap_open_w);
+    return;
+  }
+
+  if_list = get_interface_list(&err, err_str);
+  if (if_list == NULL && err == CANT_GET_INTERFACE_LIST) {
+    simple_dialog(ESD_TYPE_WARN, NULL, "Can't get list of interfaces: %s",
+                       err_str);
+  }
   
-  cap_open_w = gtk_window_new(GTK_WINDOW_TOPLEVEL);
-  gtk_window_set_title(GTK_WINDOW(cap_open_w), "Ethereal: Capture Preferences");
+  cap_open_w = dlg_window_new("Ethereal: Capture Preferences");
+  gtk_signal_connect(GTK_OBJECT(cap_open_w), "destroy",
+       GTK_SIGNAL_FUNC(capture_prep_destroy_cb), NULL);
+
+  /* Accelerator group for the accelerators (or, as they're called in
+     Windows and, I think, in Motif, "mnemonics"; Alt+<key> is a mnemonic,
+     Ctrl+<key> is an accelerator). */
+  accel_group = gtk_accel_group_new();
+  gtk_window_add_accel_group(GTK_WINDOW(cap_open_w), accel_group);
   
-  /* Container for each row of widgets */
   main_vb = gtk_vbox_new(FALSE, 3);
   gtk_container_border_width(GTK_CONTAINER(main_vb), 5);
   gtk_container_add(GTK_CONTAINER(cap_open_w), main_vb);
   gtk_widget_show(main_vb);
   
+  /* Table : container of the first 4 rows */
+  table = gtk_table_new (4, 2, FALSE);
+  gtk_table_set_row_spacings(GTK_TABLE (table), 5);
+  gtk_table_set_col_spacings(GTK_TABLE (table), 5);
+  gtk_container_add(GTK_CONTAINER(main_vb), table);
+  gtk_widget_show(table);
+
   /* Interface row */
-  if_hb = gtk_hbox_new(FALSE, 3);
-  gtk_container_add(GTK_CONTAINER(main_vb), if_hb);
-  gtk_widget_show(if_hb);
   
   if_lb = gtk_label_new("Interface:");
-  gtk_box_pack_start(GTK_BOX(if_hb), if_lb, FALSE, FALSE, 0);
+  gtk_table_attach_defaults(GTK_TABLE(table), if_lb, 0, 1, 0, 1);
   gtk_widget_show(if_lb);
   
   if_cb = gtk_combo_new();
   if (if_list != NULL)
     gtk_combo_set_popdown_strings(GTK_COMBO(if_cb), if_list);
-  if (cf.iface)
-    gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(if_cb)->entry), cf.iface);
+  if (cfile.iface)
+    gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(if_cb)->entry), cfile.iface);
   else if (if_list)
     gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(if_cb)->entry), if_list->data);
-  gtk_box_pack_start(GTK_BOX(if_hb), if_cb, FALSE, FALSE, 0);
+  gtk_table_attach_defaults(GTK_TABLE(table), if_cb, 1, 2, 0, 1);
   gtk_widget_show(if_cb);
   
-  while (if_list) {
-    g_free(if_list->data);
-    if_list = g_list_remove_link(if_list, if_list);
-  }
+  free_interface_list(if_list);
 
   /* Count row */
-  count_hb = gtk_hbox_new(FALSE, 3);
-  gtk_container_add(GTK_CONTAINER(main_vb), count_hb);
-  gtk_widget_show(count_hb);
   
   count_lb = gtk_label_new("Count:");
-  gtk_box_pack_start(GTK_BOX(count_hb), count_lb, FALSE, FALSE, 0);
+  gtk_table_attach_defaults(GTK_TABLE(table), count_lb, 0, 1, 1, 2);
   gtk_widget_show(count_lb);
   
   count_list = g_list_append(count_list, count_item1);
-  if (cf.count) {
-    snprintf(count_item2, 15, "%d", cf.count);
+  if (cfile.count) {
+    snprintf(count_item2, 15, "%d", cfile.count);
     count_list = g_list_append(count_list, count_item2);
   }
 
   count_cb = gtk_combo_new();
   gtk_combo_set_popdown_strings(GTK_COMBO(count_cb), count_list);
-  gtk_box_pack_start(GTK_BOX(count_hb), count_cb, FALSE, FALSE, 0);
+  gtk_table_attach_defaults(GTK_TABLE(table), count_cb, 1, 2, 1, 2);
   gtk_widget_show(count_cb);
 
   while (count_list)
     count_list = g_list_remove_link(count_list, count_list);
 
   /* Filter row */
-  filter_hb = gtk_hbox_new(FALSE, 3);
-  gtk_container_add(GTK_CONTAINER(main_vb), filter_hb);
-  gtk_widget_show(filter_hb);
   
   filter_bt = gtk_button_new_with_label("Filter:");
   gtk_signal_connect(GTK_OBJECT(filter_bt), "clicked",
-    GTK_SIGNAL_FUNC(filter_dialog_cb), NULL);
-  gtk_box_pack_start(GTK_BOX(filter_hb), filter_bt, FALSE, TRUE, 0);
+    GTK_SIGNAL_FUNC(filter_browse_cb), NULL);
+  gtk_table_attach_defaults(GTK_TABLE(table), filter_bt, 0, 1, 2, 3);
   gtk_widget_show(filter_bt);
   
   filter_te = gtk_entry_new();
-  if (cf.cfilter) gtk_entry_set_text(GTK_ENTRY(filter_te), cf.cfilter);
+  if (cfile.cfilter) gtk_entry_set_text(GTK_ENTRY(filter_te), cfile.cfilter);
   gtk_object_set_data(GTK_OBJECT(filter_bt), E_FILT_TE_PTR_KEY, filter_te);
-  gtk_box_pack_start(GTK_BOX(filter_hb), filter_te, TRUE, TRUE, 0);
+  gtk_table_attach_defaults(GTK_TABLE(table), filter_te, 1, 2, 2, 3);
   gtk_widget_show(filter_te);
   
   /* File row */
-  file_hb = gtk_hbox_new(FALSE, 1);
-  gtk_container_add(GTK_CONTAINER(main_vb), file_hb);
-  gtk_widget_show(file_hb);
   
   file_bt = gtk_button_new_with_label("File:");
-  gtk_box_pack_start(GTK_BOX(file_hb), file_bt, FALSE, FALSE, 3);
+  gtk_table_attach_defaults(GTK_TABLE(table), file_bt, 0, 1, 3, 4);
   gtk_widget_show(file_bt);
   
   file_te = gtk_entry_new();
-  gtk_box_pack_start(GTK_BOX(file_hb), file_te, TRUE, TRUE, 3);
+  gtk_table_attach_defaults(GTK_TABLE(table), file_te, 1, 2, 3, 4);
   gtk_widget_show(file_te);
 
   gtk_signal_connect(GTK_OBJECT(file_bt), "clicked",
@@ -225,7 +224,7 @@ capture_prep_cb(GtkWidget *w, gpointer d)
   gtk_box_pack_start(GTK_BOX(caplen_hb), snap_lb, FALSE, FALSE, 6);
   gtk_widget_show(snap_lb);
 
-  adj = (GtkAdjustment *) gtk_adjustment_new((float) cf.snap,
+  adj = (GtkAdjustment *) gtk_adjustment_new((float) cfile.snap,
     MIN_PACKET_SIZE, WTAP_MAX_PACKET_SIZE, 1.0, 10.0, 0.0);
   snap_sb = gtk_spin_button_new (adj, 0, 0);
   gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (snap_sb), TRUE);
@@ -233,12 +232,26 @@ capture_prep_cb(GtkWidget *w, gpointer d)
   gtk_box_pack_start (GTK_BOX(caplen_hb), snap_sb, FALSE, FALSE, 3); 
   gtk_widget_show(snap_sb);
   
-  sync_cb = gtk_check_button_new_with_label("Update list of packets in real time");
+  promisc_cb = dlg_check_button_new_with_label_with_mnemonic(
+               "Capture packets in _promiscuous mode", accel_group);
+  gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(promisc_cb), promisc_mode);
+  gtk_container_add(GTK_CONTAINER(main_vb), promisc_cb);
+  gtk_widget_show(promisc_cb);
+
+  sync_cb = dlg_check_button_new_with_label_with_mnemonic(
+               "_Update list of packets in real time", accel_group);
   gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(sync_cb), sync_mode);
   gtk_container_add(GTK_CONTAINER(main_vb), sync_cb);
   gtk_widget_show(sync_cb);
 
-  resolv_cb = gtk_check_button_new_with_label("Enable name resolution");
+  auto_scroll_cb = dlg_check_button_new_with_label_with_mnemonic(
+               "_Automatic scrolling in live capture", accel_group);
+  gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(auto_scroll_cb), auto_scroll_live);
+  gtk_container_add(GTK_CONTAINER(main_vb), auto_scroll_cb);
+  gtk_widget_show(auto_scroll_cb);
+
+  resolv_cb = dlg_check_button_new_with_label_with_mnemonic(
+               "Enable _name resolution", accel_group);
   gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(resolv_cb), g_resolving_actif);
   gtk_container_add(GTK_CONTAINER(main_vb), resolv_cb);
   gtk_widget_show(resolv_cb);
@@ -271,27 +284,91 @@ capture_prep_cb(GtkWidget *w, gpointer d)
   gtk_object_set_data(GTK_OBJECT(cap_open_w), E_CAP_FILE_TE_KEY,  file_te);
   gtk_object_set_data(GTK_OBJECT(cap_open_w), E_CAP_COUNT_KEY, count_cb);
   gtk_object_set_data(GTK_OBJECT(cap_open_w), E_CAP_SNAP_KEY,  snap_sb);
+  gtk_object_set_data(GTK_OBJECT(cap_open_w), E_CAP_PROMISC_KEY, promisc_cb);
   gtk_object_set_data(GTK_OBJECT(cap_open_w), E_CAP_SYNC_KEY,  sync_cb);
+  gtk_object_set_data(GTK_OBJECT(cap_open_w), E_CAP_AUTO_SCROLL_KEY, auto_scroll_cb);
   gtk_object_set_data(GTK_OBJECT(cap_open_w), E_CAP_RESOLVE_KEY,  resolv_cb);
 
+  /* Catch the "activate" signal on the frame number and file name text
+     entries, so that if the user types Return there, we act as if the
+     "OK" button had been selected, as happens if Return is typed if some
+     widget that *doesn't* handle the Return key has the input focus. */
+  dlg_set_activate(filter_te, ok_bt);
+  dlg_set_activate(file_te, ok_bt);
+
+  /* Catch the "key_press_event" signal in the window, so that we can catch
+     the ESC key being pressed and act as if the "Cancel" button had
+     been selected. */
+  dlg_set_cancel(cap_open_w, cancel_bt);
+
+  /* XXX - why does not
+
+     gtk_widget_grab_focus(if_cb);
+
+    give the initial focus to the "Interface" combo box?
+
+    Or should I phrase that as "why does GTK+ continually frustrate
+    attempts to make GUIs driveable from the keyboard?"  We have to
+    go catch the activate signal on every single GtkEntry widget
+    (rather than having widgets whose activate signal is *not*
+    caught not catch the Return keystroke, so that it passes on,
+    ultimately, to the window, which can activate the default
+    widget, i.e. the "OK" button); we have to catch the "key_press_event"
+    signal and have the handler check for ESC, so that we can have ESC
+    activate the "Cancel" button; in order to support Alt+<key> mnemonics
+    for buttons and the like, we may have to construct an accelerator
+    group by hand and set up the accelerators by hand (if that even
+    works - I've not tried it yet); we have to do a "gtk_widget_grab_focus()"
+    to keep some container widget from getting the initial focus, so that
+    you don't have to tab into the first widget in order to start typing
+    in it; and it now appears that you simply *can't* make a combo box
+    get the initial focus, at least not in the obvious fashion. Sigh.... */
+
   gtk_widget_show(cap_open_w);
 }
 
 static void
 capture_prep_file_cb(GtkWidget *w, gpointer file_te)
 {
+  GtkWidget *caller = gtk_widget_get_toplevel(w);
   GtkWidget *fs;
 
+  /* Has a file selection dialog box already been opened for that top-level
+     widget? */
+  fs = gtk_object_get_data(GTK_OBJECT(caller), E_FILE_SEL_DIALOG_PTR_KEY);
+
+  if (fs != NULL) {
+    /* Yes.  Just re-activate that dialog box. */
+    reactivate_window(fs);
+    return;
+  }
+
   fs = gtk_file_selection_new ("Ethereal: Capture File");
 
   gtk_object_set_data(GTK_OBJECT(fs), E_CAP_FILE_TE_KEY, file_te);
 
+  /* Set the E_FS_CALLER_PTR_KEY for the new dialog to point to our caller. */
+  gtk_object_set_data(GTK_OBJECT(fs), E_FS_CALLER_PTR_KEY, caller);
+
+  /* Set the E_FILE_SEL_DIALOG_PTR_KEY for the caller to point to us */
+  gtk_object_set_data(GTK_OBJECT(caller), E_FILE_SEL_DIALOG_PTR_KEY, fs);
+
+  /* Call a handler when the file selection box is destroyed, so we can inform
+     our caller, if any, that it's been destroyed. */
+  gtk_signal_connect(GTK_OBJECT(fs), "destroy",
+           GTK_SIGNAL_FUNC(cap_prep_fs_destroy_cb), NULL);
+
   gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION(fs)->ok_button),
     "clicked", (GtkSignalFunc) cap_prep_fs_ok_cb, fs);
 
   /* Connect the cancel_button to destroy the widget */
   gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION(fs)->cancel_button),
     "clicked", (GtkSignalFunc) cap_prep_fs_cancel_cb, fs);
+
+  /* Catch the "key_press_event" signal in the window, so that we can catch
+     the ESC key being pressed and act as if the "Cancel" button had
+     been selected. */
+  dlg_set_cancel(fs, GTK_FILE_SELECTION(fs)->cancel_button);
   
   gtk_widget_show(fs);
 }
@@ -311,10 +388,28 @@ cap_prep_fs_cancel_cb(GtkWidget *w, gpointer data)
   gtk_widget_destroy(GTK_WIDGET(data));
 }  
 
+static void
+cap_prep_fs_destroy_cb(GtkWidget *win, gpointer data)
+{
+  GtkWidget *caller;
+
+  /* Get the widget that requested that we be popped up.
+     (It should arrange to destroy us if it's destroyed, so
+     that we don't get a pointer to a non-existent window here.) */
+  caller = gtk_object_get_data(GTK_OBJECT(win), E_FS_CALLER_PTR_KEY);
+
+  /* Tell it we no longer exist. */
+  gtk_object_set_data(GTK_OBJECT(caller), E_FILE_SEL_DIALOG_PTR_KEY, NULL);
+
+  /* Now nuke this window. */
+  gtk_grab_remove(GTK_WIDGET(win));
+  gtk_widget_destroy(GTK_WIDGET(win));
+}
+
 static void
 capture_prep_ok_cb(GtkWidget *ok_bt, gpointer parent_w) {
-  GtkWidget *if_cb, *filter_te, *file_te, *count_cb, *snap_sb, *sync_cb,
-            *resolv_cb;
+  GtkWidget *if_cb, *filter_te, *file_te, *count_cb, *snap_sb, *promisc_cb,
+            *sync_cb, *auto_scroll_cb, *resolv_cb;
   gchar *if_text;
   gchar *if_name;
   gchar *filter_text;
@@ -325,24 +420,26 @@ capture_prep_ok_cb(GtkWidget *ok_bt, gpointer parent_w) {
   file_te   = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w), E_CAP_FILE_TE_KEY);
   count_cb  = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w), E_CAP_COUNT_KEY);
   snap_sb   = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w), E_CAP_SNAP_KEY);
+  promisc_cb = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w), E_CAP_PROMISC_KEY);
   sync_cb   = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w), E_CAP_SYNC_KEY);
+  auto_scroll_cb = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w), E_CAP_AUTO_SCROLL_KEY);
   resolv_cb = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w), E_CAP_RESOLVE_KEY);
 
   if_text =
     g_strdup(gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(if_cb)->entry)));
   if_name = strtok(if_text, " \t");
   if (if_name == NULL) {
-    simple_dialog(ESD_TYPE_WARN, NULL,
+    simple_dialog(ESD_TYPE_CRIT, NULL,
       "You didn't specify an interface on which to capture packets.");
     g_free(if_name);
     return;
   }
-  if (cf.iface)
-    g_free(cf.iface);
-  cf.iface = g_strdup(if_name);
+  if (cfile.iface)
+    g_free(cfile.iface);
+  cfile.iface = g_strdup(if_name);
   g_free(if_text);
 
-  /* XXX - don't try to get clever and set "cf.filter" to NULL if the
+  /* XXX - don't try to get clever and set "cfile.filter" to NULL if the
      filter string is empty, as an indication that we don't have a filter
      and thus don't have to set a filter when capturing - the version of
      libpcap in Red Hat Linux 6.1, and versions based on later patches
@@ -351,10 +448,10 @@ capture_prep_ok_cb(GtkWidget *ok_bt, gpointer parent_w) {
      no filter is set, which means no packets arrive as input on that
      socket, which means Ethereal never sees any packets. */
   filter_text = gtk_entry_get_text(GTK_ENTRY(filter_te));
-  if (cf.cfilter)
-    g_free(cf.cfilter);
+  if (cfile.cfilter)
+    g_free(cfile.cfilter);
   g_assert(filter_text != NULL);
-  cf.cfilter = g_strdup(filter_text); 
+  cfile.cfilter = g_strdup(filter_text); 
 
   save_file = gtk_entry_get_text(GTK_ENTRY(file_te));
   if (save_file && save_file[0]) {
@@ -365,16 +462,20 @@ capture_prep_ok_cb(GtkWidget *ok_bt, gpointer parent_w) {
     save_file = NULL;
   }
 
-  cf.count = atoi(gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(count_cb)->entry)));
+  cfile.count = atoi(gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(count_cb)->entry)));
+
+  cfile.snap = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(snap_sb));
+  if (cfile.snap < 1)
+    cfile.snap = WTAP_MAX_PACKET_SIZE;
+  else if (cfile.snap < MIN_PACKET_SIZE)
+    cfile.snap = MIN_PACKET_SIZE;
 
-  cf.snap = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(snap_sb));
-  if (cf.snap < 1)
-    cf.snap = WTAP_MAX_PACKET_SIZE;
-  else if (cf.snap < MIN_PACKET_SIZE)
-    cf.snap = MIN_PACKET_SIZE;
+  promisc_mode = GTK_TOGGLE_BUTTON (promisc_cb)->active;
 
   sync_mode = GTK_TOGGLE_BUTTON (sync_cb)->active;
 
+  auto_scroll_live = GTK_TOGGLE_BUTTON (auto_scroll_cb)->active;
+
   g_resolving_actif = GTK_TOGGLE_BUTTON (resolv_cb)->active;
 
   gtk_widget_destroy(GTK_WIDGET(parent_w));
@@ -389,150 +490,32 @@ capture_prep_close_cb(GtkWidget *close_bt, gpointer parent_w)
   gtk_widget_destroy(GTK_WIDGET(parent_w));
 }
 
-struct search_user_data {
-       char    *name;
-       int     found;
-};
-
-static GList *
-get_interface_list() {
-  GList  *il = NULL;
-  gint    nonloopback_pos = 0;
-  struct  ifreq *ifr, *last;
-  struct  ifconf ifc;
-  struct  ifreq ifrflags;
-  int     sock = socket(AF_INET, SOCK_DGRAM, 0);
-  struct search_user_data user_data;
-  pcap_t *pch;
-  gchar   err_str[PCAP_ERRBUF_SIZE];
-
-  if (sock < 0)
-  {
-    simple_dialog(ESD_TYPE_WARN, NULL,
-      "Can't list interfaces: error opening socket.");
-    return NULL;
-  }
+static void
+capture_prep_destroy_cb(GtkWidget *win, gpointer user_data)
+{
+  GtkWidget *capture_prep_filter_w;
+  GtkWidget *fs;
 
-  /* Since we have to grab the interface list all at once, we'll make
-     plenty of room */
-  ifc.ifc_len = 1024 * sizeof(struct ifreq);
-  ifc.ifc_buf = malloc(ifc.ifc_len);
-
-  if (ioctl(sock, SIOCGIFCONF, &ifc) < 0 ||
-    ifc.ifc_len < sizeof(struct ifreq))
-  {
-    simple_dialog(ESD_TYPE_WARN, NULL,
-      "Can't list interfaces: SIOCGIFCONF error: %s", strerror(errno));
-    goto fail;
-  }
+  /* Is there a filter edit/selection dialog associated with this
+     Capture Preferences dialog? */
+  capture_prep_filter_w = gtk_object_get_data(GTK_OBJECT(win), E_FILT_DIALOG_PTR_KEY);
 
-  ifr  = (struct ifreq *) ifc.ifc_req;
-  last = (struct ifreq *) ((char *) ifr + ifc.ifc_len);
-  while (ifr < last)
-  {
-    /*
-     * Skip addresses that begin with "dummy", or that include a ":"
-     * (the latter are Solaris virtuals).
-     */
-    if (strncmp(ifr->ifr_name, "dummy", 5) == 0 ||
-       strchr(ifr->ifr_name, ':') != NULL)
-      goto next;
-
-    /*
-     * If we already have this interface name on the list, don't add
-     * it (SIOCGIFCONF returns, at least on BSD-flavored systems, one
-     * entry per interface *address*; if an interface has multiple
-     * addresses, we get multiple entries for it).
-     */
-    user_data.name = ifr->ifr_name;
-    user_data.found = FALSE;
-    g_list_foreach(il, search_for_if_cb, &user_data);
-    if (user_data.found)
-      goto next;
-
-    /*
-     * Get the interface flags.
-     */
-    memset(&ifrflags, 0, sizeof ifrflags);
-    strncpy(ifrflags.ifr_name, ifr->ifr_name, sizeof ifrflags.ifr_name);
-    if (ioctl(sock, SIOCGIFFLAGS, (char *)&ifrflags) < 0) {
-      if (errno == ENXIO)
-        goto next;
-      simple_dialog(ESD_TYPE_WARN, NULL,
-        "Can't list interfaces: SIOCGIFFLAGS error on %s: %s",
-        ifr->ifr_name, strerror(errno));
-      goto fail;
-    }
-
-    /*
-     * Skip interfaces that aren't up.
-     */
-    if (!(ifrflags.ifr_flags & IFF_UP))
-      goto next;
-
-    /*
-     * Skip interfaces that we can't open with "libpcap".
-     * Open with the minimum packet size - it appears that the
-     * IRIX SIOCSNOOPLEN "ioctl" may fail if the capture length
-     * supplied is too large, rather than just truncating it.
-     */
-    pch = pcap_open_live(ifr->ifr_name, MIN_PACKET_SIZE, 0, 0, err_str);
-    if (pch == NULL)
-      goto next;
-    pcap_close(pch);
-
-    /*
-     * If it's a loopback interface, add it at the end of the list,
-     * otherwise add it after the last non-loopback interface,
-     * so all loopback interfaces go at the end - we don't want a
-     * loopback interface to be the default capture device unless there
-     * are no non-loopback devices.
-     */
-    if ((ifrflags.ifr_flags & IFF_LOOPBACK) ||
-       strncmp(ifr->ifr_name, "lo", 2) == 0)
-      il = g_list_insert(il, g_strdup(ifr->ifr_name), -1);
-    else {
-      il = g_list_insert(il, g_strdup(ifr->ifr_name), nonloopback_pos);
-      /* Insert the next non-loopback interface after this one. */
-      nonloopback_pos++;
-    }
-
-next:
-#ifdef HAVE_SA_LEN
-    ifr = (struct ifreq *) ((char *) ifr + ifr->ifr_addr.sa_len + IFNAMSIZ);
-#else
-    ifr = (struct ifreq *) ((char *) ifr + sizeof(struct ifreq));
-#endif
+  if (capture_prep_filter_w != NULL) {
+    /* Yes.  Destroy it. */
+    gtk_widget_destroy(capture_prep_filter_w);
   }
 
-  free(ifc.ifc_buf);
-  close(sock);
+  /* Is there a file selection dialog associated with this
+     Print File dialog? */
+  fs = gtk_object_get_data(GTK_OBJECT(win), E_FILE_SEL_DIALOG_PTR_KEY);
 
-  return il;
-
-fail:
-  if (il != NULL) {
-    g_list_foreach(il, free_if_cb, NULL);
-    g_list_free(il);
+  if (fs != NULL) {
+    /* Yes.  Destroy it. */
+    gtk_widget_destroy(fs);
   }
-  free(ifc.ifc_buf);
-  close(sock);
-  return NULL;
-}
 
-static void
-search_for_if_cb(gpointer data, gpointer user_data)
-{
-       struct search_user_data *search_user_data = user_data;
-
-       if (strcmp((char *)data, search_user_data->name) == 0)
-               search_user_data->found = TRUE;
-}
-
-static void
-free_if_cb(gpointer data, gpointer user_data)
-{
-       g_free(data);
+  /* Note that we no longer have a "Capture Preferences" dialog box. */
+  cap_open_w = NULL;
 }
 
 #endif /* HAVE_LIBPCAP */